[Chapter 37] 37.5 Reference in Numerical Order
Author: Bryan Costales & Eric Allman
Date: 1999-01-06T22:03:13Z

#

| Chapter 37 Debugging with -d |

## 37.5 Reference in Numerical Order

The sendmail debugging switches vary from vendor to vendor and from version to version. This section is specific to V8.8.0 sendmail. These switches are perhaps best used with a copy of the sendmail source by your side. Be further advised that many of the internal details shown here will change as sendmail continues to evolve and improve.

In this section we provide a detailed description of each combination of debugging category and level. In Table 37.2 each debugging category and level that we consider useful for the system administrator who is trying to solve a mail problem is marked with "useful." The others provide such complex and sophisticated output that they may be of use only to those with access to the source. Those marked in the section column with a "n/a" are debugging switches that were introduced in the sendmail source too late for documentation in this edition. All are presented in ascending numerical order, first by category, then by level within each category.

Note that for all categories a `-d`category and a `-d`category`.1` are always equivalent.

Table 37.2: Debugging Switches by Category
Category |  | It is | Description
--- | --- | --- | ---
-d0.1 | Section 37.5.1, -d0.1 | useful | Print version information
-d0.4 | Section 37.5.2, -d0.4 | useful | Our name and aliases
-d0.10 | Section 37.5.3, -d0.10 |  | Operating System defines
-d0.15 | Section 37.5.4, -d0.15 | useful | Dump delivery agents
-d0.20 | Section 37.5.5, -d0.20 | useful | Print network address of each interface
-d0.22 | Section 37.5.6, -d0.22 |  | Show uname() failure
-d0.40 | Section 37.5.7, -d0.40 |  | Show scanning of interfaces
-d0.44 | Section 37.5.8, -d0.44 |  | Print addresses of strings
-d0.90 | Section 37.5.9, -d0.90 | obsolete | Print first 10 rule sets
-d1.1 | Section 37.5.10, -d1.1 |  | Show sender information
-d1.5 | Section 37.5.11, -d1.5 |  | Dump the sender address
-d2.1 | Section 37.5.12, -d2.1 |  | End with finis()
-d2.9 | Section 37.5.13, -d2.9 |  | Show file descriptors with dumpfd()
-d3.1 | Section 37.5.14, -d3.1 |  | Print the load average
-d3.5 | Section 37.5.15, -d3.5 |  | Print load average
-d3.15 | Section 37.5.16, -d3.15 |  | Print three load averages
-d3.20 | Section 37.5.17, -d3.20 |  | Show offset for load average
-d3.30 | Section 37.5.18, -d3.30 |  | Show result of decision to queue
-d4.80 | Section 37.5.19, -d4.80 | useful | Trace enoughspace()
-d5.4 | Section 37.5.20, -d5.4 |  | Tick for queued events
-d5.5 | Section 37.5.21, -d5.5 |  | Events set and cleared
-d5.6 | Section 37.5.22, -d5.6 |  | Show events triggered
-d6.1 | Section 37.5.23, -d6.1 | useful | Show failed mail
-d6.5 | Section 37.5.24, -d6.5 |  | The current error state
-d6.20 | Section 37.5.25, -d6.20 |  | Show sender of return to sender
-d7.1 | Section 37.5.26, -d7.1 |  | The Queue filename
-d7.2 | Section 37.5.27, -d7.2 |  | Show assigned queue filename
-d7.9 | Section 37.5.28, -d7.9 |  | Dump file descriptor for the qf file
-d7.20 | Section 37.5.29, -d7.20 |  | Show queue names being tried
-d8.1 | Section 37.5.30, -d8.1 | useful | Failure of MX search (low level)
-d8.2 | Section 37.5.31, -d8.2 | useful | Call to getcanonname(3)
-d8.3 | Section 37.5.32, -d8.3 | useful | Trace dropped local hostnames
-d8.5 | Section 37.5.33, -d8.5 | useful | Hostname being tried in getcanonname(3)
-d8.7 | Section 37.5.34, -d8.7 | useful | Yes/no response to -d8.5
-d8.8 | Section 37.5.35, -d8.8 | useful | MX lookup gets wrong type
-d8.20 | Section 37.5.36, -d8.20 |  | Inconsistency in returned information
-d9.1 | Section 37.5.37, -d9.1 |  | Canonify hostname and RFC1413 queries
-d9.3 | Section 37.5.38, -d9.3 |  | Show raw RFC1413 reply
-d9.10 | Section 37.5.39, -d9.10 |  | Show RFC1413 query being sent
-d10.1 | Section 37.5.40, -d10.1 |  | Show recipient delivery
-d10.2 | Section 37.5.41, -d10.2 |  | Dump controlling user's address
-d10.5 | Section 37.5.42, -d10.5 |  | Show don't send to MeToo address
-d10.100 | Section 37.5.43, -d10.100 |  | Predelivery file descriptor dump
-d11.1 | Section 37.5.44, -d11.1 | useful | Trace delivery
-d11.2 | Section 37.5.45, -d11.2 | useful | Show the uid/gid running as during delivery
-d11.20 | Section 37.5.46, -d11.20 |  | Show tried D= directories
-d12.1 | Section 37.5.47, -d12.1 | useful | Show mapping of relative host
-d13.1 | Section 37.5.48, -d13.1 | useful | Show delivery
-d13.5 | Section 37.5.49, -d13.5 |  | Show addresses that we should not send to
-d13.6 | n/a |  | Trace envelope stripping, dropping, and moving
-d13.10 | Section 37.5.50, -d13.10 |  | Trace sendenvelope()
-d13.20 | Section 37.5.51, -d13.20 |  | Show final mode
-d13.21 | n/a |  | Show final send queue
-d13.25 | n/a |  | Watch owner deliveries
-d13.29 | Section 37.5.52, -d13.29 |  | Show autoqueueing
-d13.30 | Section 37.5.53, -d13.30 |  | Show envelopes being split
-d14.2 | Section 37.5.54, -d14.2 |  | Show header field commas
-d15.1 | Section 37.5.55, -d15.1 |  | Show network get request activity
-d15.2 | Section 37.5.55 |  | Incoming connections
-d15.101 | Section 37.5.57, -d15.101 |  | Kernel TCP debugging
-d16.1 | Section 37.5.58, -d16.1 |  | Outgoing Connections
-d16.101 | Section 37.5.59, -d16.101 |  | Kernel TCP debugging
-d17.1 | Section 37.5.60, -d17.1 |  | List MX hosts
-d17.9 | Section 37.5.61, -d17.9 |  | Show randomizing MX records
-d18.1 | Section 37.5.62, -d18.1 |  | Show SMTP replies
-d18.2 | Section 37.5.63, -d18.2 |  | Show entry to MAIL From:
-d18.100 | Section 37.5.64, -d18.100 |  | Pause on SMTP read error
-d19.1 | Section 37.5.65, -d19.1 |  | Show ESMTP MAIL and RCPT parameters
-d20.1 | Section 37.5.66, -d20.1 | useful | Show resolving delivery agent: parseaddr()
-d21.1 | Section 37.5.67, -d21.1 |  | Trace rewriting rules
-d21.2 | Section 37.5.68, -d21.2 | useful | Trace $& macros
-d21.3 | Section 37.5.69, -d21.3 |  | Show subroutine calls
-d21.4 | Section 37.5.70, -d21.4 |  | Result after rewriting by a rule
-d21.10 | Section 37.5.71, -d21.10 |  | Announce failure
-d21.12 | Section 37.5.72, -d21.12 |  | Announce success and show LHS
-d21.15 | Section 37.5.73, -d21.15 |  | Show $digit replacement
-d21.35 | Section 37.5.74, -d21.35 |  | Show token by token LHS matching
-d21.36 | Section 37.5.75, -d21.36 |  | Trace class matching in the LHS
-d22.1 | Section 37.5.76, -d22.1 | useful | Trace tokenizing an address: prescan()
-d22.11 | Section 37.5.77, -d22.11 | useful | Show address before prescan
-d22.12 | Section 37.5.78, -d22.12 |  | Show address after prescan
-d22.36 | Section 37.5.79, -d22.36 |  | Show each token
-d22.101 | Section 37.5.80, -d22.101 |  | Trace low-level state machine
-d24.4 | Section 37.5.81, -d24.4 |  | Trace address allocation
-d24.5 | Section 37.5.82, -d24.5 |  | Trace assembly of tokens
-d24.6 | Section 37.5.83, -d24.6 |  | Show result of buildaddr()
-d25.1 | Section 37.5.84, -d25.1 | useful | Trace "sendtolist"
-d26.1 | Section 37.5.85, -d26.1 |  | Trace recipient queueing
-d26.8 | Section 37.5.86, -d26.8 |  | Trace self-destructing addresses
-d26.10 | Section 37.5.87, -d26.10 |  | Show full send queue in testselfdestruct
-d27.1 | Section 37.5.88, -d27.1 | useful | Trace aliasing
-d27.2 | Section 37.5.89, -d27.2 | useful | Include file, self-reference, error on home
-d27.3 | Section 37.5.90, -d27.3 | useful | Forwarding path and alias wait
-d27.4 | Section 37.5.91, -d27.4 | useful | Print not safe
-d27.5 | Section 37.5.92, -d27.5 |  | Trace aliasing with printaddr()
-d27.8 | Section 37.5.93, -d27.8 |  | Show setting up an alias map
-d27.9 | Section 37.5.94, -d27.9 | useful | Show uid/gid changes with :include: reads
-d27.14 | Section 37.5.95, -d27.14 |  | Show controlling user that caused change in identity
-d27.20 | Section 37.5.96, -d27.20 |  | Show how alias will be looked up in a map
-d28.1 | Section 37.5.97, -d28.1 | useful | Trace user database transactions
-d28.2 | Section 37.5.98, -d28.2 |  | Show no match
-d28.4 | Section 37.5.99, -d28.4 |  | Show result of lookup
-d28.8 | Section 37.5.100, -d28.8 |  | Try hes_getmailhost()
-d28.16 | Section 37.5.101, -d28.16 |  | MX records for forward host
-d28.20 | Section 37.5.102, -d28.20 |  | Show udb lookup
-d28.80 | Section 37.5.103, -d28.80 |  | Preview lookups
-d29.1 | Section 37.5.104, -d29.1 |  | Special rewrite of local recipient
-d29.4 | Section 37.5.105, -d29.4 | useful | Trace fuzzy matching
-d29.5 | Section 37.5.106, -d29.5 |  | Preview rule set 5
-d29.7 | Section 37.5.107, -d29.7 |  | Show overaliasing fuzzy fallback
-d30.1 | Section 37.5.108, -d30 |  | Trace processing of header
-d30.2 | Section 37.5.109, -d30.2 |  | Eat from
-d30.3 | Section 37.5.110, -d30.3 |  | Show a to-less header being added
-d30.35 | Section 37.5.111, -d30.35 |  | Trace collect states
-d30.94 | Section 37.5.112, -d30.94 |  | Trace collect states
-d31.2 | Section 37.5.113, -d31.2 | useful | Trace processing of headers
-d31.6 | Section 37.5.141_6 |  | Is header known?
-d32.1 | Section 37.5.115, -d32.1 |  | Show collected headers
-d32.2 | Section 37.5.116, -d32.2 |  | Show ARPA mode with setsender
-d33.1 | Section 37.5.117, -d33.1 |  | Watch crackaddr()
-d34.1 | Section 37.5.118, -d34.1 |  | Watch header assembly for output
-d34.11 | Section 37.5.119, -d34.11 | useful | Trace header generation and skipping
-d35.9 | Section 37.5.120, -d35.9 | useful | Macro values defined
-d35.14 | Section 37.5.121, -d35.14 |  | Macro identification
-d35.24 | Section 37.5.122, -d35.24 |  | Macro expansion
-d36.5 | Section 37.5.123, -d36.5 |  | Trace processing by stab()
-d36.9 | Section 37.5.124, -d36.9 |  | Show hash bucket
-d36.90 | Section 37.5.125, -d36.90 |  | Trace function applied to all symbols
-d37.1 | Section 37.5.126, -d37.1 | useful | Trace setting of options
-d37.8 | Section 37.5.127, -d37.8 | useful | Trace adding of words to a class
-d38.2 | Section 37.5.128, -d38.2 | useful | Show map opens and failures
-d38.3 | Section 37.5.129, -d38.3 |  | Show passes
-d38.4 | Section 37.5.130, -d38.4 | useful | Show result of map open
-d38.9 | Section 37.5.131, -d38.9 |  | Trace map closings and appends
-d38.10 | Section 37.5.132, -d38.10 |  | Trace NIS search for end of aliases
-d38.12 | Section 37.5.133, -d38.12 |  | Trace map stores
-d38.19 | Section 37.5.134, -d38.19 | useful | Trace switch map finds
-d38.20 | Section 37.5.135, -d38.20 | useful | Trace map lookups
-d38.44 | Section 37.5.136, -d38.44 |  | Show nis_getcanonname() record
-d39.1 | Section 37.5.137, -d39.1 |  | Display %digit database mapping
-d40.1 | Section 37.5.138, -d40.1 |  | Trace processing of the queue
-d40.3 | Section 37.5.139, -d40.3 |  | Show envelope flags
-d40.4 | Section 37.5.140, -d40.4 |  | Show qf file lines as they are read
-d40.8 | Section 37.5.141, -d40.8 |  | Show reasons for failure
-d40.9 | Section 37.5.142, -d40.9 |  | Show qf and lock file descriptors
-d40.32 | Section 37.5.143, -d40.32 |  | Dump the send queue
-d41.1 | Section 37.5.144, -d41.1 | useful | Trace queue ordering
-d41.2 | Section 37.5.145, -d41.2 |  | Cannot open qf
-d41.49 | Section 37.5.146, -d41.49 |  | Show excluded (skipped) queue files
-d41.50 | Section 37.5.147, -d41.50 |  | Show every file in the queue
-d42.2 | Section 37.5.148, -d42.2 |  | Show connection checking
-d42.5 | Section 37.5.149, -d42.5 |  | Trace caching and uncaching connections
-d43.1 | Section 37.5.150, -d43.1 |  | Trace MIME conversions
-d43.3 | Section 37.5.151, -d43.3 |  | See the final MIME boundary name
-d43.5 | Section 37.5.152, -d43.5 |  | Watch search for boundaries
-d43.8 | Section 37.5.153, -d43.8 |  | Show the calculations
-d43.35 | Section 37.5.154, -d43.35 |  | Show boundary lines as emitted
-d43.36 | Section 37.5.155, -d43.36 |  | Show content transfer encoding
-d43.40 | Section 37.5.156, -d43.40 |  | Show parse of Content-Type: header
-d43.99 | Section 37.5.157, -d43.99 |  | Print the leading/following comments
-d43.100 | Section 37.5.158, -d43.100 |  | Mark collect() and putheader()
-d44.4 | Section 37.5.159, -d44.4 |  | Trace safefile()
-d44.5 | Section 37.5.160, -d44.5 | useful | Trace writable()
-d45.1 | Section 37.5.161, -d45.1 |  | Show envelope sender
-d45.3 | Section 37.5.162, -d45.3 |  | Show saved domain
-d45.5 | Section 37.5.163, -d45.5 |  | Show don't send to sender
-d46.9 | Section 37.5.164, -d46.9 |  | Show xf file's descriptors
-d48.2 | Section 37.5.165, -d48.2 | useful | Trace calls to the check_ rule sets
-d49.1 | Section 37.5.166, -d49.1 |  | Trace checkcompat()
-d50.1 | Section 37.5.167, -d50.1 |  | Show envelope being dropped
-d50.2 | Section 37.5.168, -d50.2 |  | Show Booleans
-d50.10 | Section 37.5.169, -d50.10 |  | Also show the send queue
-d51.4 | Section 37.5.170, -d51.4 |  | Show queue entries being unlocked
-d51.104 | Section 37.5.171, -d51.104 |  | Prevent unlink of xf file
-d52.1 | Section 37.5.172, -d52.1 |  | Show isconnect from controlling TTY
-d52.100 | Section 37.5.173, -d52.100 |  | Prevent disconnect from controlling tty
-d53.99 | Section 37.5.174, -d53.99 |  | Trace xclose()
-d54.1 | Section 37.5.175, -d54.1 |  | Show error return and output message
-d54.8 | Section 37.5.176, -d54.8 |  | Show message and flags
-d55.60 | Section 37.5.177, -d55.60 |  | Show file locking
-d56.1 | Section 37.5.178, -d56.1 |  | Persistent host status tracing
-d56.2 | Section 37.5.179, -d56.2 |  | More persistent host status tracing
-d56.12 | Section 37.5.180, -d56.12 |  | Perform a sanity check
-d56.80 | Section 37.5.181, -d56.80 |  | Trace creating the path to the status file
-d56.93 | Section 37.5.182, -d56.93 |  | Dump MCI record for the host
-d57.2 | Section 37.5.183, -d57.2 |  | Monitor vsnprintf() overflows
-d59.1 | Section 37.5.184, -d59 |  | XLA from contrib
-d60.1 | Section 37.5.185, -d60.1 | useful | Trace map lookups inside rewrite()
-d61.10 | Section 37.5.186, -d61.10 |  | Trace gethostbyname()
-d62.1 | Section 37.5.187, -d62.1 |  | Log file descriptors before and after all deliveries
-d62.8 | Section 37.5.188, -d62.8 |  | Log file descriptors before each delivery
-d62.10 | Section 37.5.189, -d62.10 |  | Log file descriptors after each delivery
-d80.1 | Section 37.5.190, -d80.1 |  | Content-Length: header (Sun enhancement)
-d81.1 | Section 37.5.191, -d81.1 |  | > option for remote mode (Sun enhancement)
-d91.100 | Section 37.5.192, -d91.100 |  | Log caching and uncaching connections
-d99.100 | Section 37.5.193, -d99.100 | useful | Prevent backgrounding the daemon

### 37.5.1 -d0.1

Print version information

(useful)

> The `-d0.1` (a.k.a. `-d0`) debugging switch previously prevented sendmail from forking and detaching itself, but that function has been moved to the `-d99.100` debugging switch. The `-d0.1` debugging switch now just tells sendmail to print information about its version:

> >     Version 8.8.4
> >     Compiled with:   LOG MATCHGECOS NAMED_BIND NDBM NEWDB NETINET NETUNIX
> >                      NIS
> >     SYSTEM IDENTITY (after readcf):
> >                 (short domain name) $w = here
> >             (canonical domain name) $j = here.US.EDU
> >                    (subdomain name) $m = US.EDU
> >                         (node name) $k = here

> The `Version` is the current version of sendmail. Note that for Sun the number may look like `SMI-8.7.5`.

> The `Compiled with:` lists the compile-time definitions that where specified when sendmail is compiled. All the available definitions are listed in Table 18.3 in Section 18.8, "Alphabetized Reference".

> The `SYSTEM IDENTITY` shows the value assigned to four important macros. The meaning of each macro is contained in Table 31.7 in Section 31.10, "Alphabetized Reference".

### 37.5.2 -d0.4

Our name and aliases

(useful)

> The `-d0.4` debugging switch tells sendmail to print several additional lines of information:

> >     Version 8.8.4
> >     Compiled with:   LOG MATCHGECOS NAMED_BIND NDBM NEWDB NETINET NETUNIX
> >                      NIS
> >     canonical name: here.US.EDU                            additional
> >      UUCP nodename: here                                   additional
> >             a.k.a.: [123.45.67.89]                         additional
> >     ============ SYSTEM IDENTITY (after readcf) ============
> >                 (short domain name) $w = here
> >             (canonical domain name) $j = here.US.EDU
> >                    (subdomain name) $m = US.EDU
> >                         (node name) $k = here
> >     ========================================================

> To find the canonical name of the local host, sendmail calls gethostname(). If that call fails, the name localhost is used. The hostname is then looked up with the internal routine sm_gethostbyname(), which gathers additional information (such as other names and addresses for the machine) and fixes several bugs in some operating system's versions of the gethostby... routines. Next the canonical name for the local host is looked up. For operating systems that normally support switched services, the name is looked up as specified. For systems that specify switched services in the configuration file's `ServiceSwitchFile` option (see Section 34.8.61, ServiceSwitchFile), switched services are not used because the configuration file has not been read yet. (This canonicalization process can be traced with the `-61.10` debugging switch.) If the canonical is found and that name contains a dot, sendmail saves the part of the name to the right of the leftmost dot as the domain name in the `$m` macro (see Section 31.10.24, $m). It also appends the part of the name to the left of the leftmost dot to the class `w` (see Section 32.5.8, $=w). If the canonical name doesn't contain a dot, the `$m` macro is undefined, and the whole name is appended to the class `w`.

> In addition, sendmail also sets the `$k` macro (see Section 31.10.21, $k) to be the correct UUCP name for the machine. It uses uname(3), if available, to find that name (see Section 18.8.51, TRUST-POPEN); otherwise, it uses the same strategy as for class `w` above.

> Then sendmail lists any other names or addresses (this latter in square brackets) that it found. If it finds any, it prints the name prefixed by `a.k.a.:` and appends each to the class `w`. The aliases listed are only those found using gethostbyname(3). To see each entry as it is added to the class `w`, use the `-d37.8` debugging switch.

> Finally, sendmail scans the network hardware to find any other names associated with interfaces. If the ioctl(2) call to get that information fails, the `-d0.4` debugging switch causes sendmail to print that failure:

> >     SIOGIFCONF failed:  reason here

> If any are found, each is printed with an `a.k.a.:` prefix and added to the class macro `w`.

### 37.5.3 -d0.10

Operating System Defines

> The `-d0.10` debugging switch causes sendmail to print all the operating system specific definitions that were used to compile your specific version of sendmail. This output prints after the "Compiled with:" information described above:

> >     OS Defines: HASFLOCK HASGETUSERSHELL HASINITGROUPS HASLSTAT
> >                     HASSETREUID HASSETSID HASSETVBUF HASUNAME IDENTPROTO
> >                     IP_SRCROUTE
> >     Kernel symbols: /vmunix
> >        Config file: /etc/sendmail.cf
> >       Proc Id file: /etc/sendmail.pid

> The `OS Defines` are described in Table 18.3 in Section 18.8. Most are automatically determined during compilation; others are specified in Makefile.

> The `Kernel symbols` is the name of file that is accessed to determine the load average. It is automatically defined correctly when conf.c is compiled. The location of the configuration file and the process identifier file are defined in the Makefile and conf.h in the sendmail source (see Section 18.8.34, PATH...).

### 37.5.4 -d0.15

Dump delivery agents

(useful)

> The -d0.15 debugging switch causes sendmail to display how it interpreted its delivery agent definitions. The clarity and completeness of the delivery agent information vary with the version of sendmail. See the `=M` rule-testing command (Section 38.4.2, "Show Delivery Agents with =M") for an example of this output.

### 37.5.5 -d0.20

Print network address of each interface

(useful)

> When sendmail scans the network hardware to find other names for the local host, it uses only those names that are new. Each new name was printed by the `-d0.4` debugging switch above. To see every name that sendmail finds, new and old alike, use the `-d0.20` debugging switch:

> >     128.32.201.55                                        already found
> >     127.0.0.1                                            found new
> >             a.k.a.: [127.0.0.1]

### 37.5.6 -d0.22

Show uname() failure

> Ordinarily, if the UUCP name for the local host cannot be found (if uname(3) fails), sendmail silently uses the leftmost component of the canonical name as the UUCP name. To see whether uname(3) failed - and, if so why - you can use the `-d0.22` debugging switch:

> >     uname failed (reason for failure here)

### 37.5.7 -d0.40

Announce scanning of interfaces

> The `-d0.40` debugging switch causes sendmail to announce that it is about to scan for network interfaces:

> >     scanning for interface specific names, ifc_len=64
> >             a.k.a.: [127.0.0.1]

> The `ifc_len` is the size in bytes of the configuration list returned by the kernel.

### 37.5.8 -d0.44

Print addresses of strings

> The `-d0.44` debugging switch causes sendmail to prefix certain lists of strings that it prints with the address in memory of each string and an equal sign. With this debugging level, part of the output produced by the `-d21.12` debugging switch would look like this:

> >     --- rule fails
> >     ---trying rule:
> >             0009ec68=@
> >             0009ec78=$*
> >     --- rule fails

> This debugging level can be useful to the programmer who wishes to modify the sendmail source. It might, for example, be helpful in designing more efficient string storage.

### 37.5.9 -d0.90

Print first 10 rule sets

(obsolete)

> The `-d0.90` debugging switch causes sendmail to display its internal interpretations of the first 10 rewriting rules it took from the configuration file. The rule sets are printed in numeric order, rather than in the order in which they appeared in the configuration file. The rewriting rules are printed under each rule set (but these are in the order in which they appeared in the configuration file). Rule sets that are declared but lack rewriting rules are not printed. Note that defined macros in the RHS are expanded (the value used) when the configuration file is parsed. Also note that expressions like `$+` may be printed as control characters (e.g., `^A`) under older versions of sendmail.

> The preferred way to view individual rule sets is with the `-bt` rule-testing mode's `=S` command (see Section 38.4.1, "Show Rules in a Rule Set with =S").

### 37.5.10 -d1.1

Show sender information

> Although there are many kinds of information that one might like to trace about the sender of an email message, sendmail provides the means to trace only one of them. The `-d1.1` (a.k.a. `-d1`) debugging switch causes sendmail to print its interpretation of whom the message is from (the name of the sender as it was used in the envelope):

> >     From person = "sender"

> Here, `sender` is the user portion of the mail address of the sender. This output is most useful when combined with the `-f` command-line switch (which sets the name of the sender from the command line; see Section 36.7.21, -f and -r).

### 37.5.11 -d1.5

Dump the sender address

> The `-d1.5` debugging switch causes additional information about the sender to be printed. That output looks like this:

> >     main: QDONTSEND output of printaddr() here (see Section 37.3.1, "The Output Produced by printaddr()")

> The QDONTSEND means that the sender is not a recipient and so should not get a copy of the message. That is followed by the output of the printaddr() routine.

### 37.5.12 -d2.1

End with finis()

> Ordinarily, sendmail exits silently when it is done (unless an error causes an error message to be printed). The `-d2.1` (a.k.a. `-d2`) debugging switch causes sendmail to print three useful values when it exits. The message it prints looks like this:

> >     ====finis: stat num e_id=qid e_flags=flags

> The `num` is the final value of the sendmail program's global `ExitStat` variable. It is usually updated to contain the latest error value as defined in <sysexits.h>. See Section 36.5, "sendmail's exit() Status" for a detailed description of the possible exit values.

> The `qid` is either the queue identifier (such as SAA24069) or the NOQUEUE if the message was never assigned an identifier (such as if it was never queued).

> The `flags` is a hexadecimal representation of the possible envelope flags followed by a text representation of those flags in angle brackets with the leading `EF_` removed, for example,

> >     201003<OLDSTYLE,INQUEUE,GLOBALERRS,HAS_DF>

> These are the envelope flags that were in effect with the current envelope when sendmail exited. The possible values are shown in Table 37.3.

> Table 37.3: Hexadecimal Envelope Flags
> Text | Hex | Description
> --- | --- | ---
> EF_OLDSTYLE | `0000001` | Use spaces (not commas) in headers
> EF_INQUEUE | `0000002` | This message is fully queued
> EF_NO_BODY_RETN | `0000004` | Omit message body on error
> EF_CLRQUEUE | `0000008` | Disk copy is no longer needed
> EF_SENDRECEIPT | `0000010` | Send a return receipt
> EF_FATALERRS | `0000020` | Fatal errors occurred
> EF_KEEPQUEUE | `0000040` | Keep queue files always
> EF_RESPONSE | `0000080` | This is an error or return receipt
> EF_RESENT | `0000100` | This message is being forwarded
> EF_VRFYONLY | `0000200` | Verify only (don't expand aliases)
> EF_WARNING | `0000400` | Warning message has been sent
> EF_QUEUERUN | `0000800` | This envelope is from queue
> EF_GLOBALERRS | `0001000` | Treat errors as global
> EF_PM_NOTIFY | `0002000` | Send return mail to postmaster
> EF_METOO | `0004000` | Send to me too
> EF_LOGSENDER | `0008000` | Need to log the sender
> EF_NORECEIPT | `0010000` | Suppress all return-receipts
> EF_HAS8BIT | `0020000` | At least one 8-bit character in body
> EF_NL_NOT_EOL | `0040000` | Don't accept raw newline as end-of-line
> EF_CRLF_NOT_EOL | `0080000` | Don't accept carriage-return/line-feed as end-of-line
> EF_RET_PARAM | `0100000` | SMTP RCPT command had RET argument
> EF_HAS_DF | `0200000` | Set when df file is instantiated
> EF_IS_MIME | `0400000` | Really is a MIME message
> EF_DONT_MIME | `0800000` | This message is not MIME-able

> For example, if the message were fully queued and required a DSN return receipt, the flags would print as

> >     e_flags=12<INQUEUE,SENDRECEIPT>

> Note that this line of output is also produced by the `-d13.1`, `-d40.3`, and `-d50.1` debugging switches but under different circumstances.

### 37.5.13 -d2.9

Show file descriptors with dumpfd()

> The `-d2.9` debugging switch tells sendmail to display the properties of each open file descriptor. That output is produced by the dumpfd() routine, and each line of output is for a single file descriptor:

> >     num: fl=flags mode=mode type stats

> Here, the `num` is the number of the open file descriptor. Note that descriptors 0, 1, and 2 are usually tied to the standard input, output, and error output.

> The `flags` is a hexadecimal representation of the state flags associated with a file descriptor. F_GETFL is used with ioctl(2) to fetch each, and all are described in <sys/fcntlcom.h>.

> The `mode` is printed in octal and is the st_mode associated with an fstat(2) of the file descriptor. The `type` examines the file type portion of the st_mode and prints SOCK for a socket, CHR: for a character special device, BLK: for a block special device, FIFO: for a first-in-first-out file, DIR: for a directory, LNK: for a symbolic link, and nothing otherwise (e.g., nothing if it is a file).

> The `stats` are printed for all but the socket. They look like this:

> >     dev=major/minor ino=inum nlink=nlink u/gid=uid/gid size=bytes

> Here the `dev=` shows the major and minor device numbers for the device that the file descriptor is associated with. The `inum` is the inode number on the disk (if there is one) and `nlink` is the number of hard links to the file on disk. The `uid/gid` shows the user and group ownership associated with the file descriptor. The `size` is the number of bytes in a file, and 0 for almost everything else.

> For a socket, the `stats` part of each line looks like this:

> >     [addr]/port-> host

> Here, `addr` is the IP address of the local end of the socket. If the connection is of type AF_INET, the port number of the connection is also shown as `/port`. The `host` is the hostname, as returned by getpeername(3), of the connecting host. If any of these cannot be found, the error string associated with errno is printed parenthetically in its place.

> The `-d7.9`, `-d40.9`, and `-d46.9` debugging switches also print a line like this for specific file descriptors. Also if sendmail is run with the `-d10.100` switch, or if sendmail fails to open a tf queue file (see Section 23.2.6, "The Temporary qf Rewrite Image: tf"), or if sendmail exited because of too many open files, it will syslog all its open file descriptors within this format.

### 37.5.14 -d3.1

Print load average

> The sendmail program queues mail, rather than delivering it, if the load average (number of processes in the run queue) exceeds the value set by the `QueueLA` (`x`) option (see Section 34.8.50, QueueLA (x)). Exceeding that value also prevents messages that are already in the queue from being delivered (prevents a queue run). If the load average becomes higher than the value of the `RefuseLA` (`X`) option (see Section 34.8.54, RefuseLA (X)), sendmail rejects incoming SMTP connections until the load average drops.

> The `-d3.1` debugging switch (a.k.a. `-d3`) causes sendmail to print the load average found by its internal getla() routine each time that routine is called:

> >     getla: la

> Here, `la` is the current load average printed as an integer. If sendmail was compiled with LA_TYPE==LA_ZERO (see Section 18.8.14, LA-TYPE), the following will be printed to show that your sendmail binary completely lacks load averaging support:

> >     getla: ZERO

> The `-d3.1` debugging switch also causes sendmail to print any errors it encounters while obtaining the load average.

> >     getla: open(/dev/kmem): error

> Here, `/dev/kmem` is the device that is used to access kernel memory. The `error` is the system error that caused the failure, such as "Permission denied" if sendmail is not properly sgid to the group kmem.

> >     getla: nlist(unix): error

> The nlist(3) function extracts a list of symbols from an executable binary (among them the symbol for the load average). The binary that it extracts is the kernel whose pathname is `unix` (such as /vmunix for SunOS 4.x). Here, the `error` is the reason nlist(3) failed. One possibility is that you booted from a nonstandard kernel name (such as /vmunix.new) and the expected file didn't exist:

> >     getla: nlist(unix, la) ==> 0

> If the expected kernel exists (`unix`) but the machine was booted from a different kernel, the symbol representing the load average may not be found. In that instance, `la` is the name of the kernel variable that sendmail was trying to find.

### 37.5.15 -d3.5

Print load average

> The load average that sendmail uses is averaged over the last minute. Internally, the kernel keeps track of three load averages. In addition to the last minute, it also tracks the last 5 and 15 minutes. The `-d3.5` debugging switch causes V8 sendmail to print the load average over the last minute:

> >     getla: averun = 1min

### 37.5.16 -d3.15

Print three load averages

> The `-d3.15` debugging switch causes V8 sendmail to print all three load averages:

> >     getla: averun = 1min, 5min, 15min

> Here, the three load averages are printed either in integer or in floating point, depending on the setting of LA_TYPE (see Section 18.8.14).

### 37.5.17 -d3.20

Show offset for load average

> The nlist(3) routine (described above) provides the offset into the kernel file where the value of the load average is found. The `-d3.20` debugging switch causes that offset to be displayed:

> >     getla: symbol address = offset

> Here, the `offset` is printed in hexadecimal. The load average is read by seeking in the kernel file and reading it. If the seek or read fails, the `-d3.1` debugging switch causes sendmail to print:

> >     getla: seek or read: error

> This can indicate a wrong or corrupted kernel image.

### 37.5.18 -d3.30

Show result of decision to queue

> The internal routine shouldqueue() is called just before a mail message is delivered to recipients. That routine determines whether mail will be delivered or queued on the basis of the current load average and message `priority`. Upon entry it prints:

> >     shouldqueue: CurrentLA=load, pri=priority

> If the `CurrentLA` is less than the limit set by the `QueueLA` (`x`) option (see Section 34.8.50), sendmail prints:

> >     FALSE (CurrentLA < QueueLA)

> Then the calculation described in Section 34.8.49, QueueFactor (q) for the `QueueFactor` (`q`) option is performed using the `pri` priority. The result is printed as one of the following, where TRUE represents a zero result and FALSE represents a nonzero result:

> >     TRUE (by calculation)
> >     FALSE (by calculation)

### 37.5.19 -d4.80

Trace enoughspace()

(useful)

> The `MinFreeBlocks` (`b`) option (see Section 34.8.40, MinFreeBlocks (b)) defines the minimum number of disk blocks that must be reserved on the queue disk. If an incoming SMTP message will fill the disk beyond this minimum, the message is rejected.

> The `-d4.80` debugging switch [1] traces the enoughspace() routine in conf.c. That routine examines the disk space and allows or disallows incoming mail.

> > [1] No `-d4.1` (a.k.a. `-d4`) information is available.

> >     enoughspace: no threshold

> This debugging output says that no limit was defined with the `MinFreeBlocks` (`b`) option.

> >     enoughspace: bavail=haveblocks need=needblocks

> This debugging output shows that the number of blocks free (available) on the disk is `haveblocks` and that the number of blocks required by incoming mail is `needblocks`. Note that `haveblocks` will always be -1 if sendmail was compiled with SFS_TYPE set to SFS_NONE (see Section 18.8.40, SFS-TYPE).

> >     enoughspace failure: min=boption need=needblocks

> If the required number of blocks (`needblocks`) exceeds the minimum reserved as defined by the `MinFreeBlocks` (`b`) option (`boption`), use of the disk is disallowed.

### 37.5.20 -d5.4

Tick for queued events

> Throughout its many possible levels of forks and children, sendmail must keep track of timeouts - the maximum amount of time it should wait for an event to occur. For example, a child must not wait forever for an SMTP greeting message, because the program at the other end may never provide that message (because it died or is just too busy).

> To keep track of which child should be notified at which time, sendmail maintains an internal queue of events. The sendmail program uses the SIGALARM signal and the alarm(2) system call to set the interval it waits to next check its queue of events for timeouts. That interval (called a tick) is the period of the timeout itself, or if the timeout is scheduled for the present or past, the interval is three seconds. The `-d5.4` debugging switch [2] causes sendmail to print the current time whenever the queue of events is examined:

> > [2] There is no `-d5.1` (a.k.a. `-d5`) information.

> >     tick: now=time

> Here, time is the current time in seconds as returned by time(2).

### 37.5.21 -d5.5

Events set and cleared

> Events are set by the process (child or parent) that needs a timeout. The `-d5.5` debugging switch causes sendmail to print the information that is used to set up for that timeout:

> >     setevent: intvl=secs, for=timeo, func=addr, arg=pass, ev=evnt

> The information is the timeout interval in seconds (`secs`), the time (now plus the interval) in seconds that the timeout will occur (`timeo`), the address in memory of the subroutine that will be called if a timeout occurs (`addr`), the argument to be passed to that subroutine (`pass`), and the address in memory of the C language structure that contains this information (`evnt`). The `addr` of the function to be called can be converted to a function name by running nm(1) on an unstripped binary of sendmail. For example, if the following output was produced by /usr/lib/sendmail:

> >     setevent: intvl=3600, for=802463800, func=3ebc4, arg=0, ev=94b68

> you could find the function name associated with the address `3ebc4` by running

> >     %  nm /usr/lib/sendmail | grep 3ebc4
> >     0003ebc4 t _readtimeout

> Here, the result is the name `readtimeout`, which corresponds to the function readtimeout() in util.c.

> When an event is cleared because a timeout was no longer needed, sendmail prints:

> >     clrevent: ev=evnt

> Here, `evnt` is the address in memory of the C language structure that stored the event information. This is the same as the last item printed by `setevent` above.

### 37.5.22 -d5.6

Show events triggered

> The `-d5.6` debugging switch tells sendmail to print the following information when a timeout occurs:

> >     tick: ev=evnt, func=addr, arg=pass, pid=pid

> This shows that the event stored in the C language structure, whose address in memory is `evnt`, has timed out. The subroutine whose address in memory is `addr` will be called with an argument of `pass`. The process identification number of the parent process that asked for the timeout is shown as `pid`.

### 37.5.23 -d6.1

Show failed mail

(useful)

> Mail can fail for a wide variety of reasons. The way that sendmail handles errors is determined by the setting of the `ErrorMode` (`e`) option (see Section 34.8.24, ErrorMode (e)) in the configuration file. The `-d6.1` (a.k.a. `-d6`) debugging switch causes sendmail to print the error-handling mode that is in effect at the time it first begins to handle failed mail:

> >     savemail, errorMode = char, id = qid, ExitStat = err
> >     e_from=  output of printaddr() here (see Section 37.3.1)

> Here, `char` is either: `p` for print errors; `m` for mail back errors; `w` for write back errors; `e` for special BERKnet processing; or `q` for "don't print anything" (all of which are described under the `ErrorMode` option in Section 34.8.24). The `qid` is the queue identifier (such as KAA15019). The `err` is the error that caused the message to fail (as defined in <sysexits.h>). And `e_from=` uses printaddr() to print details about the sender's address.

> If the error-processing mode is `m` (for mail back) and the `-d6.1` debugging switch is in effect, sendmail prints details about how the message is being returned to the sender:

> >     ***Return To Sender: msg=reason, depth=num, e=addr, returnq=
> >      output of printaddr() here (see Section 37.3.1)

> Here, `reason` is a quoted string of text that explains why the mail failed. This may be an SMTP reply string. The `num` is zero for normal delivery and one for error delivery. The `addr` is the location in memory of the information about the current envelope. Finally, sendmail calls printaddr() to print the details of the queue of recipients (`returnq=`) for the current message.

### 37.5.24 -d6.5

The current error state

> The `-d6.5` debugging switch tells sendmail to print the error state it was in when it finished processing the error that caused the message to fail:

> >     state num

> If `num` is 7 (successful delivery), nothing is printed. Otherwise, the above message is printed, and the value of `num` represents one of the states shown in Table 37.4.

> Table 37.4: Error Handling States
> State | Description
> --- | ---
> 0 | Report to sender's terminal
> 1 | Mail back to sender
> 2 | Messages have already been returned
> 3 | Save in ~/dead.letter
> 4 | Return to postmaster
> 5 | Save in /usr/tmp/dead.letter
> 6 | Leave the locked queue/transcript files
> 7 | The message has been successfully delivered

### 37.5.25 -d6.20

Show sender of return to sender

> The `-d6.20` debugging switch tells sendmail to print additional information to that printed by `-d6.1`. Specifically, it prints, via printaddr(), the address information about the sender of returned mail:

> >     ***Return To Sender: msg=reason, depth=num, e=addr, returnq=
> >     output of printaddr() here (see Section 37.3.1)
> >     Sendq= output of printaddr() here

### 37.5.26 -d7.1

The Queue filename

> The sendmail program stores mail messages in its queue for a variety of reasons. For example, the `SuperSafe` (`s`) option (see Section 34.8.67, SuperSafe (s)) causes it to queue all messages just to be safe. Also, messages that cannot be delivered because of a temporary lack of resources (or for any correctable reason) are queued for later delivery.

> Mail messages are stored in the queue in two parts. A data part contains the body of the message. An information part stores headers and other information about the message. The filenames of the two parts are identical but for the first two letters. A `df` begins the name of the data part, and a `qf` begins the name of the information part. A third type of queue file begins with the letters `xf` and is a "transcript" file that holds error messages produced during delivery.

> To ensure that these filenames do not conflict with the names of files that may already be in the queue, sendmail uses the following pattern to create new names:

> >     qfHAApid

> Here, `pid` is the process identification number of the incarnation of sendmail that is trying to create the file. Because sendmail often fork(2)'s to process the queue, the `pid` is likely unique and therefore creates a unique name.

> The `H` represents the current hour of the day (using a 24-hour clock) and prefixes the `AA`. It is constructed by adding the current hour to the letter `A` (thus 00:23 would produce `A+0=A`, while 15:45 would produce `A+15=P`). Although it is not recommended, the hour character can be useful in viewing the queue (with the `-bp` command-line switch) to observe the particular hours, if any, that messages tend to queue. The hour prefix does not increment.

> If sendmail cannot create a file (because a file with that name already exists), it increments the rightmost `A` of the `AA` part of the name to a `B` and tries again. It continues this process, incrementing the right from `A` to `Z` and the left from `A` to `~` until it succeeds. If a unique name cannot be found, sendmail has failed in its attempt to queue the message. The last filename tried is:

> >     qfH~Zpid

> This name is unlikely to ever appear, because the clocking provides for over 1600 possible unique names. With some versions of sendmail, however, it may appear if the queue directory is not writable. For example, the `-C` command-line switch, when used by a normal user, might cause sendmail to give up its root privilege, thus causing this message to be printed.

> The `-d7.1` (a.k.a. `-d7`) debugging switch causes sendmail to print the portion of the queue name that is common to all the files that constitute a single queued message.

> >     queuename: assigned id HAApid, env=addr

> Here, sendmail prints the identifier portion of the filename (the `H` `AA`, or whatever letters succeeded, and the `pid`) that is common to the `df`, `qf`, and `xf` files. The `addr` is the address in memory of the C language structure that describes the envelope for the mail message that is queued.

### 37.5.27 -d7.2

Show assigned queue file name

> The `-d7.2` debugging switch tells sendmail to print the full filename of the file that it just created in the queue directory:

> >     queuename: letterfHAApid

> The first `letter` of the name is either `d`, `q`, or `x`. The `pid` is the process identification number of the sendmail process that created the file.

### 37.5.28 -d7.9

Dump file descriptor for the qf file

> Once sendmail successfully opens its `qf` file, it has established the unique identifier. The `-d7.9` debugging switch causes sendmail to dump the file-descriptor for that open file:

> >     lockfd= output of dumpfd() here (see Section 37.5.13)

### 37.5.29 -d7.20

Show queue names being tried

> The `-d7.20` debugging switch causes sendmail to print each filename that it is attempting to try as it clocks the `AA` in the name from `AA` to `~Z`:

> >     queuename: trying qfHAA16391
> >     queuename: trying qfHAB16391
> >     queuename: trying qfHAC16391
> >     queuename: trying qfHAD16391
> >     ...  and so on

### 37.5.30 -d8.1

DNS name resolution

(useful)

> Name resolution is the process of determining a machine's IP address based on its fully qualified domain name. This is done by using the Domain Name System (DNS). The process that sendmail uses to resolve a name is described in Section 21.2, "How sendmail Uses DNS".

> When sendmail finds that a hostname is really an MX (mail exchanger) record, it attempts to look up the A record for the host that handles mail receipt. That request may fail for a variety of reasons. If the `-d8.1` (a.k.a. `-d8`) debugging switch is specified, sendmail produces the following message:

> >     getmxrr: res_search(host) failed (errno=err, h_errno=herr)

> Here, `host` is the hostname that was being looked up, `err` is the system error number (if any) from <errno.h>, and `herr` is the resolver specific error from <netdb.h> as shown in Table 37.5.

> Table 37.5: Resolver Errors from netdb.h
> Value | Mnemonic | Description
> --- | --- | ---
> 1 | HOST_NOT_FOUND | Host not found (authoritative answer returned)
> 2 | TRY_AGAIN | Nonauthoritative server not found or server failure
> 3 | NO_RECOVERY | Nonrecoverable errors and refusals
> 4 | NO_DATA | Valid name but no record of requested type

### 37.5.31 -d8.2

Call to getcanonname(3)

(useful)

> The routine dns_getcanonname() in domain.c of the sendmail source converts a hostname to a fully qualified domain name. This routine is called only if DNS is used to look up hostnames, as determined by the `ResolverOptions` (`I`) option (see Section 34.8.55, ResolverOptions (I)) and the `ServiceSwitchFile` option (see Section 34.8.61). If it is, dns_getcanonname() can be called from two places: during startup to get the values for `$w`, `$j`, and `$m` (see Section 37.5.2) or when a host is looked up via the `$[` and `$]` canonify-operators (see Section 28.6.6, "Canonicalize Hostname: $[ and $]").

> The `-d8.2` debugging switch shows the hostname before it is fully qualified with this call:

> >     dns_getcanonname(host, flag)

> If the `flag` is nonzero, calls to the getmxrr() routine (which looks up MX records) are also traced. On entry to that routine, sendmail will print:

> >     getmxrr(host, droplocalhost=bool)

> The `host` is the hostname that MX records are being looked up for. The `bool`, if nonzero, means that all MX records that are less preferred than the local host (as determined by `$=w`) will be discarded. If zero, they will be retained.

> The `-d8.2` debugging switch also causes sendmail to show the result of processing the `ResolverOptions` (`I`) option's settings (see Section 34.8.55) while reading the configuration file:

> >     _res.options = hex, HasWildcardMX = 1 or 0

> The `hex` is a hexadecimal representation of the `state` structure's `options` variable as described in <resolv.h>. The value of HasWildcardMX is determined by its prefix (`+` or `-`) when listed with the `ResolverOptions` (`I`) option.

### 37.5.32 -d8.3

Trace dropped local hostnames

(useful)

> If a hostname is dropped because `bool` (above) is nonzero, the `-d8.3` switch causes sendmail to print the following:

> >     found localhost (host) in MX list, pref=pref

> The `host` is the hostname that is being dropped. The `pref` is the preference associated with the MX record.

### 37.5.33 -d8.5

Hostname being tried in getcanonname(3)

(useful)

> The `-d8.5` debugging switch causes the getcanonname(3) routine to print the hostname it is trying to fully qualify. It shows the name with the local domain appended without the local domain appended, and at each step in between. Each try is printed as:

> >     getcanonname: trying host.domain (type)

> Here, the `type` is the type of lookup and is either ANY, A, or MX.

### 37.5.34 -d8.7

Yes/no response to -d8.5

(useful)

> The `-d8.7` debugging switch causes sendmail to print a yes or no response to each of the "trying" lines printed by `-8.5`. Yes means that the `host` could successfully be fully canonicalized. A yes answer prints just this:

> >     YES

> If the `host` could not be canonicalized, a more complex answer is printed:

> >     NO: errno=err, h_errno=herr

> The `err` is the system error number (if any) from <errno.h>, and `herr` is the resolver specific error from <netdb.h> as shown in Table 37.5.

### 37.5.35 -d8.8

Resolver debugging

(useful)

> The `-d8.8` debugging switch causes the resolver library to be put into debugging mode (if that was mode was included when that library was compiled). The `ResolverOptions` (`I`) option (see Section 34.8.55) +DEBUG also turns on this debugging mode. But be aware that turning on +DEBUG will cause a large number of screens full of output to be produced by the resolver library for every DNS lookup.

> If the name server returns an answer to an MX lookup, and if the answer is not an MX record or an error, sendmail will skip that host. The `-d8.8` debugging switch (or the resolver library being in debug mode) then causes sendmail to print the following:

> >     unexpected answer type wrongtype, size bytes

> The `wrongtype` is an integer that can be found in <arpa/nameser.h>.

### 37.5.36 -d8.20

Inconsistency in returned information

> Internally, the resolver library (libresolv.a) stores host domain names in compressed form (for transmission efficiency). We won't cover the nature of that compression. For our purposes it is sufficient to know that the sendmail program calls dn_skipname(3) from the resolver library to skip past the compressed part of a host domain name. That call should never fail, but if it does, the `-d8.20` debugging switch causes sendmail to print:

> >     qdcount failure (questions)

> The `questions` is a count of the number of queries made.

### 37.5.37 -d9.1

Canonify hostname and RFC1413 queries

> The `-d9.1` (a.k.a. `-d9`) debugging switch can be used to watch sendmail convert hostnames and addresses into canonical form. This is done by watching the host_map_lookup() function with `-d9.1`. First the hostname is looked up in the symbol table. If it exists there and if it is marked as a valid canonical entry, sendmail prints

> >     host_map_lookup(host) => CACHE canon

> Here, the name `host` was found in the symbol table. The value returned was a valid canonical name. If `host` had not been found, the `canon` would have printed as NULL.

> If sendmail is running in defer-delivery mode (see the `DeliveryMode` (`d`) option in Section 34.8.16, DeliveryMode (d)), it will skip looking up the hostname further. This is done because dial-on-demand connections should not be brought up merely to perform unnecessary DNS lookups. When sendmail skips further lookups, it prints:

> >     host_map_lookup(host) => DEFERRED

> If the name is not in the symbol table, it is looked up with the getcanonname() function. First sendmail prints:

> >     host_map_lookup(host) =>

> with no trailing newline. Then, if the canonical name is returned by getcanonname(), that returned name is printed. Otherwise, FAIL is printed. If sendmail is compiled with NAMED_BIND defined for DNS support (see Section 18.8.23, NAMED-BIND), the FAIL is followed by the resolver specific error (`herr`) from <netdb.h>:

> >     host_map_lookup(host) => herr

> The `-d9` debugging switch is also used to display identd(8) queries. When a network connection is made from a remote host to the local host, the local sendmail uses the RFC1413 identification protocol to query the remote host for the name of the user who instantiated the connection. The result of that query is printed as:

> >     getauthinfo: result

> Here, `result` is two pieces of information: an address composed of the username, an `@`, and the real name of the remote host and the IP address of that host:

> >     getauthinfo: george@fbi.dc.gov [123.45.67.8]

> If the query fails, nothing is printed.

### 37.5.38 -d9.3

Show raw RFC1413 reply

> The above information is not provided by the remote host in that clear form. Instead, sendmail needs to parse the needed information from a raw reply. The `-d9.3` debugging switch causes the raw reply to be printed:

> >     getauthinfo:  got raw_reply

### 37.5.39 -d9.10

Show RFC1413 query being sent

> The `-d9.10` debugging switch causes sendmail to display its outgoing RFC1413 query:

> >     getauthinfo: sent query

> Here, the outgoing `query` is composed of two numbers: the TCP port on the remote machine where its RFC1413 server is running, followed by a dot and the local port number for the original connection.

### 37.5.40 -d10.1

Show recipient delivery

> When sendmail is about to deliver a mail message, it has already resolved three pieces of information: which delivery agent to use, the name of the host that receives the message, and the name of one or more recipients for that message. The `-d10.1` (a.k.a. `-d10)` debugging switch tells sendmail to display information about the recipient to whom it is about to deliver:

> >     -deliver, id=mid, mailer=num, host=`hname', first user=`uname'

> Here, `mid` is the queue message identifier (such as PAA08463). The `num` is the number of the delivery agent selected. Delivery agent numbers can be displayed by using the `-d0.15` debugging switch. The `hname` is the name of the host that receives delivery. The `uname` is the name of the first of possibly many users who receive the mail message. The `uname` can be either a single name such as joe or a full forwarding address such as joe@jokes.are.us.

> When sendmail attempts delivery, it may be delivering to multiple recipients. It stores its list of recipients internally as a linked list of C language structures, each of which holds information that is specific to each recipient address. The `-d10.1` debugging switch also causes sendmail to print that information using the printaddr() routine:

> >     send to output of printaddr() here (see Section 37.3.1)

### 37.5.41 -d10.2

Dump controlling user's address

> Every recipient address may have a controlling user associated with it (see Section 23.9.2, C line). The `-d10.2` causes sendmail to dump the address of the controlling user using the printaddr() routine:

> >     ctladdr= output of printaddr() here (see Section 37.3.1)

### 37.5.42 -d10.5

Showq don't send to MeToo address

> If the `MeToo` (`m`) option (see Section 34.8.39, MeToo (m)) is set to false, the `-d10.5` debugging switch tells sendmail to dump the address that won't receive (the QDONTSEND) the mail message.

> >     deliver: QDONTSEND output of printaddr() here (see Section 37.3.1)

### 37.5.43 -d10.100

Predelivery file descriptor dump

> The `-d10.100` debugging switch tells sendmail to dump all its file descriptors just before it is about to attempt delivery.

### 37.5.44 -d11.1

Trace delivery

(useful)

> The `-d11.1` (a.k.a. `-d11`) debugging switch is used to trace message delivery. For each delivery agent the following is printed:

> >     openmailer: argv

> Here, `argv` is the `A=` array for the delivery agent, with macros expanded and printed.

> The status of remote hosts is cached internally. Before connecting to a remote host, sendmail checks its cache to see whether that host is down. If it is, it skips connecting to that host. If the `-d11.1` debugging switch is also specified, the status of the down host is printed as:

> >     openmailer: output of mci_dump() here

> The output of mci_dump() looks like this:

> >     MCI@memaddr: flags=mci_flags<flag,flag,...>,
> >     errno=mci_errno, herrno=mci_herrno, exitstat=mci_exitstat, state=mci_state,
> >     pid=mci_pid, maxsize=mci_maxsize, phase=mci_phase, mailer=mci_mailer,
> >     host=mci_host, lastuse=mci_lastuse

> The meaning of each `mci_` item in the above output is described in Table 37.6.

> Table 37.6: The Meaning of the MCI Structure Items
> Name | What prints
> --- | ---
> `mci_memaddr` | The address in memory of this C language structure
> `mci_flags` | The flag bits in hexadecimal (see Table 37.7)
> `mci_errno` | The error number of the last connection
> `mci_herrno` | The DNS h_errno of the last lookup
> `mci_exitstat` | The <sysexits.h> exit status of last connection
> `mci_state` | The current SMTP state (see Table 37.16)
> `mci_maxsize` | The maximum size message the host will accept
> `mci_pid` | The PID of the child process
> `mci_phase` | SMTP phase (string) such as "client greeting" (or NULL)
> `mci_mailer` | The (text) name of the delivery agent (or NULL)
> `mci_host` | The host's name (or NULL)
> `mci_lastuse` | Last usage time in ctime(3) format

> Table 37.7 shows what the individual flag bits in `mci_flags` mean, and the human-readable flags text that corresponds to each bit. Those text items are shown with the leading source `MCIF_` prefix removed.

> Table 37.7: The Meaning of mci_flags Hexadecimal Values
> Value | Name | Meaning
> --- | --- | ---
> 0001 | VALID | This entry is valid
> 0002 | TEMP | Don't cache this connection
> 0004 | CACHED | This connection currently in open cache
> 0008 | ESMTP | This host speaks ESMTP
> 0010 | EXPN | EXPN command supported
> 0020 | SIZE | SIZE option supported
> 0040 | 8BITMIME | BODY=8BITMIME supported
> 0080 | 7BIT | Strip this message to 7 bits
> 0100 | MULTSTAT | MAIL11V3: handles MULT status
> 0200 | INHEADER | Currently outputting header
> 0400 | CVT8TO7 | Convert from 8 to 7 bits
> 0800 | DSN | DSN extension supported
> 1000 | 8BITOK | OK to send 8-bit characters
> 2000 | CVT7TO8 | Convert from 7 to 8 bits
> 4000 | INMIME | Currently reading MIME header

> After checking to see whether the host is down, sendmail attempts to connect to it for network SMTP mail. If that connect fails, the `-d11.1` debugging switch causes the following to be printed:

> >     openmailer: makeconnection => stat=exitstatus, errno=errno

> Here, `exitstatus` is a numerical representation of the reason for the failure as documented in <sysexits.h>, and `errno` is the system-level reason for the error, as documented in <errno.h>.

> Other errors, such as failure to establish a pipe(2), or failure to fork(2), causes the following to be printed:

> >     openmailer: NULL

> This message (although it contains no information) signals that a more descriptive error message was logged with syslog(3) (see Section 26.1, "Logging with syslog").

### 37.5.45 -d11.2

Show the uid/gid running as during delivery

(useful)

> To perform delivery, sendmail often has to set its uid to something other than root's. The logic behind that process is described in Section 24.2.2. The `-d11.2` debugging switch tells sendmail to print the real and effective uid's that it is running under during delivery.

> >     openmailer: running as r/euid=ruid/euid

> Also, the `-d11.2` debugging switch causes sendmail to print any error response that may be produced by a delivery agent:

> >     giveresponse: stat=status, e->e_message=what

> Here, `status` is the error that caused delivery to fail (or succeed if it is 0) as defined in <sysexits.h>. The `what` is either the error message produced by the delivery agent or "<NULL>" if the delivery agent was silent.

### 37.5.46 -d11.20

Show tried D= directories

> Execution of a delivery agent can take place in any of a sequence of directories as defined by the `D=` delivery agent equate (see Section 30.4.3, D=). The `-d11.20` debugging switch causes each directory to be printed as it is tried:

> >     openmailer: trydir dir

> Here, `dir` is the name of the directory that sendmail is about to chdir(2) into.

### 37.5.47 -d12.1

Show mapping of relative host

(useful)

> In the SMTP RCPT command, sendmail is required to express the recipient's address relative to the local host. For domain addresses, this simply means that the address should be RFC822-compliant.

> The `-d12.1` (a.k.a. `-d12`) debugging switch causes sendmail to print the address as it appeared before it was made relative:

> >     remotename(addr)

> If the `addr` is for the sender or recipient and is being processed from a queue file, then nothing more is printed, and the `addr` is processed by rule set 3. If the delivery agent for the recipient has the `F=C` flag set (see Section 30.8.15, F=C) and the recipient address lacks a domain part, then the domain of the sender is appended, and the result is processed by rule set 3 again. Sender/recipient-specific rule sets are then applied (1 and `S=` for the sender, or 2 and `R=` for the recipient). Next, rule set 4 is applied, and any macros in the result are expanded. Finally, the fully qualified and relative address is printed as:

> >     remotename => `addr'

### 37.5.48 -d13.1

Show delivery

(useful)

> The `-d13` (a.k.a. `-d13`) debugging switch causes sendmail to display information about the recipients of each mail message as it is being delivered. The `-d13.1` debugging switch tells sendmail to print the mode of delivery and then the recipient information:

> >     SENDALL: mode dmode, id=mid, e_from output of printaddr() here (see Section 37.3.1)
> >             e_flags = envelope flags here
> >             sendqueue:
> >     output of printaddr() here (see Section 37.3.1)

> Here, dmode is one of those shown in Table 37.8. The `mid` is the queue message identifier (such as PAA08463). The address of the sender, `e_from`, is dumped by using the printaddr() routine. Then the envelope flags, `e_flags`, are dumped as described in Table 37.3. Next, information about all the recipients (`sendqueue:`) is printed by using the printaddr() routine.

> Table 37.8: Delivery Modes Used by sendall()
> Mode | Description
> --- | ---
> `i` | Interactive delivery
> `j` | Deliver w/o queueing (obsolete as of V8)
> `b` | Deliver in background
> `q` | Queue, don't deliver
> `d` | Defer, queue w/o DNS lookups
> `v` | Verify only (used internally)

> Finally, the `-d13.1` debugging switch causes sendmail to print a message every time it splits an envelope in two:

> >     sendall: split orig into new

> Here, `orig` is the original queue message identifier for the original envelope (such as PAA08463) and `new` is the identifier for the new envelope, the near identical clone of the first. Envelopes need to split if they have different owners.

### 37.5.49 -d13.5

Show addresses that we should not send to

> The `-d13.5` debugging switch is used to display addresses to which mail should not be delivered. One such address is that of the sender of the cloned envelope after a split:

> >     sendall(split): QDONTSEND output of printaddr() here (see Section 37.3.1)

> Another is the sender address (unless the `MeToo` (`m`) option, see Section 34.8.39, is set):

> >     sendall: QDONTSEND output of printaddr() here (see Section 37.3.1)

> Finally, senders who are the `owner-` of mailing lists (see Section 25.3, "Defining a Mailing List Owner") should not have mail sent to them.

> >     sendall(owner): QDONTSEND output of printaddr() here (see Section 37.3.1)

> This latter sender address is derived by a call to setsender(), which can be separately viewed with the `-d45` debugging switch.

### 37.5.50 -d13.10

Trace sendenvelope()

> The `-d13.10` debugging switch causes sendmail to print the following upon entering its internal sendenvelope() routine:

> >     sendenvelope(ident) e_flags=hex

> The ident is either the queue identifier (such as SAA24069) or the [NOQUEUE] if the message was never assigned an identifier (such as if it was never queued). The `e_flags` are dumped in hexadecimal as described in Table 37.3.

### 37.5.51 -d13.20

Show final mode

> The sendmail program's delivery mode (as initially set with the `DeliveryMode` (`d`) option; see Section 34.8.16) can change during delivery for a complex series of reasons. The `-d13.20` debugging switch causes the final delivery mode to be displayed:

> >     sendall: final mode = char

> Here, `char` is the one of the characters that can be specified for the `DeliveryMode` (`d`) option.

### 37.5.52 -d13.29

Show auto-queueing

> If, after all recipient addresses are checked, none are left to be delivered to (everyone of them was either dropped or queued), and if the `DeliveryMode` (`d`) option (see Section 34.8.16) is neither `q`, `d`, nor `v`, the `-d13.29` debugging switch will cause sendmail to print:

> >     No deliveries: auto-queuing

### 37.5.53 -d13.30

Show envelopes being split

> The process of creating another envelope for another sender is called "splitting the envelope." The `-d13.30` debugging switch causes sendmail to show its initial scanning of the send queue to count the number of envelopes (including split envelopes) that will be needed.

> >     Checking output of printaddr() here (see Section 37.3.1)

> Then, depending on the result, each owner will have one of the following printed:

> >     ... QDONTSEND
> >         ... QBADADDR|QQUEUEUP
> >         ... expensive
> >         ... deliverable

> The `Q` flags are described under the output of printaddr() in Section 37.3.1.

### 37.5.54 -d14.2

Show header field commas

> Some programs require that addresses in a list of recipients be separated from each other by space characters. This is called an "old-style" address. RFC822 requires that addressees be separated from each other with comma characters.

> The `-d14.2` [3] debugging switch tells sendmail to show each header line that may need spaces converted to commas.

> > [3] There is no `-d14.1` information.

> >     commaize(header: list)

> Here, `header` is the caption part of a header line, such as `From:`. The `list` is a sequence of one or more addresses.

### 37.5.55 -d15.1

Show network get request activity

> When sendmail runs in daemon mode, it opens a socket on a port, then listens on that socket for incoming SMTP connections. The `-d15.1` (a.k.a. `-d15`) debugging switch prints information about both of those steps. Note that `-d15.1` should usually be combined with `-d99.100`, or some output may be lost.

> Before the socket is opened, sendmail prints the following:

> >     getrequests: port 0xportno

> This shows that the port numbered `portno` (printed in hexadecimal notation) is used to open the socket. If that open fails, sendmail syslog(3)'s one of the following messages at LOG_CRIT and exits:

> >     getrequests: problem creating SMTP socket

> If the open succeeds, sendmail attempts to bind to that socket. If it cannot bind, it syslogs the following message at LOG_CRIT and exits:

> >     getrequests: can't bind socket

> After it binds, sendmail goes into a loop in which it listens for and handles incoming SMTP requests. If the listen fails, sendmail syslog(3)'s the following message at LOG_CRIT and exits:

> >     getrequests: cannot listen

> If sendmail starts to listen successfully, this `-d15.1` debugging switch causes it to print the number of the socket on which it is listening:

> >     getrequests: sockno

> This shows that sendmail is then listening on the socket whose file descriptor is `sockno`.

### 37.5.56 -d15.2

Incoming connections

> In daemon mode, sendmail waits for an incoming SMTP connection. When that connection is made, sendmail forks, and the child processes the connection from that point on. The `-d15.2` debugging switch causes sendmail to print a message that confirms that it is performing this fork. Note that `-d15.2` should usually be combined with `-d99.100`, or some output may be lost:

> >     getrequests: forking (fd = sock)

> Here, `sock` is the value of the socket being used for the connection. The `-d15.2` debugging switch also causes a message to be printed when the child process exits:

> >     getreq: returning (normal server)
> >     getreq: returning (null server)

> Here, failure of the connection to be validated (see Section 22.4.1, "Accept/Reject Connections via libwrap.a" and Section 29.10.3, "The check_relay Rule Set"), causes `null server` to be printed. A successful connection causes `normal server` to be printed.

> Finally, the `-d15.2` debugging switch causes the following to be printed every time opendaemonsocket() routine is called:

> >     opendaemonsocket()

### 37.5.57 -d15.101

Kernel TCP debugging

> On kernels that support this feature, the `-d15.101` debugging switch turns on kernel debugging for the socket that is opened to handle an incoming SMTP connection. Debugging is turned off when the socket is closed at the end of receipt of the message. The debugging information gathered can be viewed with the trpt(8) program.

### 37.5.58 -d16.1

Outgoing connections

> When mail messages are sent to a site that can be reached via a TCP/IP connection, the `-d16.1` (a.k.a. `-d16`) debugging switch causes sendmail to print one of the following messages when it is about to make the connection:

> >     makeconnection: (host [NULLADDR])             null address
> >     makeconnection: (host [0])                    no address family
> >     makeconnection: (host [[UNIX: path]])         AF_UNIX family
> >     makeconnection: (host [ip address])           AF_INET family
> >     makeconnection: (host [[LINK: name]])         AF_LINK family
> >     makeconnection: (host [Family num:0xbytes])   unknown family

> Here, `host` is the name of the host to which the connection is made. The form of the address information differs depending on the address family. If the connection can be successfully made, the `-d16.1` debugging switch then causes sendmail to print:

> >     makeconnection: fd=sock

> Here, sock is the socket descriptor that was issued for use with the socket connection.

> If the `DialDelay` option (see Section 34.8.17, DialDelay) is nonzero and the connection fails, sendmail will sleep DialDelay seconds and try again. If the `-d16.1` debugging switch is also specified, sendmail will print:

> >     Connect failed (error message); trying again...

> Here, `error message` describes the reason for the initial failure.

> If there is more than one address for a host, sendmail will try each in turn until one connects successfully. The `-d16.1` debugging switch causes the following to be printed for each failure:

> >     Connect failed (error message); trying new address....

> Note that the `-d16` debugging switch should usually be combined with the `-d99.100` debugging switch, or some output may be lost.

### 37.5.59 -d16.101

Kernel TCP debugging

> See `-d15.101`. The only difference here is that debugging is turned on for the outgoing socket.

### 37.5.60 -d17.1

List MX hosts

> When sendmail readies to deliver mail to a remote host, it looks up that host using DNS to find Mail Exchanger (MX) records. The `-d17.1` (a.k.a. `-d17`) debugging switch causes V8 sendmail to print the following:

> >     hostsignature(host) = records

> Here, `host` is the host that was looked up with DNS. The `records` is a colon-delimited list of MX records for that host. That list might contain only the original hostname if no MX records were found.

### 37.5.61 -d17.9

Show randomizing MX records

> MX records have preferences. Delivery is to the record with the lowest preference first, then to each higher preference, in turn, until a delivery succeeds. When two or more preferences are equal, V8 sendmail randomizes them so that they are tried in a different order. The order is the same each time, so this is really a pseudo-randomization (actually a hash function).

> The `-d17.9` debugging switch causes sendmail to print the following each time it randomizes:

> >     mxrand(host) = hash

> This shows that the MX records for `host` have been given a hash value of `hash`.

### 37.5.62 -d18.1

Show SMTP replies

> The process of transmitting (or receiving) a mail message using the SMTP protocol requires sendmail to send replies as its side of the dialogue. The `-d18.1` (a.k.a. `-d18`) debugging switch causes sendmail to print each reply that it sends. It prefixes what it prints with three right angle brackets:

> >     >>> RCPT To: gw@wash.dc.gov

> Note that this is the same output as produced with the `-v` command-line switch (see Section 36.7.41, -v).

> The `-d18.1` debugging switch also causes the following message to be printed to the standard output if the file descriptor for the connection is NULL:

> >     smtpmessage: NULL mci_out

> Prior to opening the connection, the `-d18.1` debugging switch causes sendmail to print:

> >     smtpinit output of mci_dump() here

> Finally, the `-d18.1` debugging switch causes sendmail to print:

> >     reply

> Each time it enters its reply() routine.

### 37.5.63 -d18.2

Show entry to MAIL From:

> The `-d18.2` debugging switch causes sendmail to show processing of the SMTP MAIL From: command that the local machine will send.

> >     smtpmailfrom: CurHost=host

> Here, `host` is the name of the current host that sendmail is dealing with.

### 37.5.64 -d18.100

Pause on SMTP read error

> The `-d18.100` debugging switch causes sendmail to pause(2) after a read error when processing the SMTP dialog. The administrator can then use ps(8) and gcore(8) to produce a core dump, which can then be examined with a debugger to determine the reason for the read error.

### 37.5.65 -d19.1

Show ESMTP MAIL and RCPT parameters

> Under Extended SMTP (ESMTP) the MAIL and RCPT command can be followed by other optional parameters. The `-d19.1` (a.k.a. `-d19`) debugging switch displays those parameters. We discuss the MAIL command first, then the RCPT command.

> #### 37.5.65.1 Show MAIL parameters

> The sendmail program recognizes four parameters that can follow the address in the SMTP MAIL command: [4] SIZE, which specifies the size in bytes of the incoming message; BODY, which specifies the nature of the message body (`8bitmime` or `7bit`); ENVID, which is used to propagate a sender-specific unique identifier for the envelope; and RET, which specifies whether or not to return the message body on an error return.

> > [4] SIZE is defined in RFC1653, BODY is defined in RFC1652, and ENVID and RET are defined in RFC1891.

> The `-d19.1` debugging switch causes sendmail to print the parameters it received:

> >     MAIL: got arg param="value"

> The `param` is one of the parameters shown above. The nature of the `value` depends on the `param`

> The `value` for SIZE is a positive integer. If SIZE lacks a value, this error is issued:

> >     501 SIZE requires a value

> When multiple, illegal SIZE values are specified, the last is the one whose value is used.

> The `value` for BODY is a case-insensitive string. It can either be `8bitmime` or `7bit`. If BODY lacks a value, the following error is issued:

> >     501 BODY requires a value

> If BODY has neither of the approved strings as its value, the following error is issued:

> >     501 Unknown BODY type bad string here

> When multiple, illegal BODY values are specified, the last is the one whose value is used.

> The `value` for ENVID is a special envelope identifier. It is composed of ASCII characters in the range `!` through `~`, excepting `+` and `=`. Characters outside that range and those two excepted characters are replaced with a `+` followed by a hexadecimal representation of the character's value (there must be exactly two hexadecimal digits). If ENVID lacks a value, the following error is issued:

> >     501 ENVID requires a value

> If the text of the value is not as described above, the following error is issued:

> >     501 Syntax error in ENVID parameter value

> If more than one ENVID specified is for a given envelope, the second results in this error:

> >     501 Duplicate ENVID parameter

> The `value` for RET is one of two possible case-insensitive strings: `hdrs` tells sendmail to return only the headers of a bounced mail message; `full` tells sendmail to return the headers and body of a bounced mail message. If no string is present, the following error is issued:

> >     501 RET requires a value

> If a string is present but is something other than `hdrs` or `full`, the following is printed:

> >     501 Bad argument bad string here

> If more than one RET is specified for a given envelope, the following error is printed:

> >     501 Duplicate RET parameter

> If the parameter is not SIZE, BODY, ENVID, or RET, the following error is issued:

> >     501 param parameter unrecognized

> #### 37.5.65.2 Show RCPT parameters

> The sendmail program recognizes two parameters that can follow the address in the SMTP RCPT command: NOTIFY, which specifies when to notify the sender; and ORCPT, which specifies the original recipient's address.

> The `-d19.1` debugging switch causes sendmail to print the parameters it received:

> >     RCPT: got arg param="value"

> The `param` is one of the parameters shown above. The nature of the `value` depends on the `param`

> The `value` for NOTIFY is either NEVER or a comma-separated list composed of SUCCESS, which means to notify the sender upon final delivery that the message was successfully delivered; FAILURE, which means to notify the sender if the message cannot be delivered; and DELAY, which means to notify the sender if the message is delayed. If there is no `value`, the following error is issued:

> >     501 NOTIFY requires a value

> If a `value` is present but it is not one of the words shown above, the following error is issued:

> >     501 Bad argument \"bad value here\"  to NOTIFY

> Multiple, illegal NOTIFY parameters in an envelope cause the subsequent values to be logically OR'd together.

> The `value` for ORCPT is an address followed by a semicolon, then an address that is encoded in the same way as the envelope identifier described for ENVID above. If that `value` is missing, the following error message is issued:

> >     501 ORCPT requires a value

> If the `value` is syntactically wrong (i.e., if the `value` does not have a valid address following the semicolon), this error message is issued:

> >     501 Syntax error in ORCPT parameter value

> If multiple ORCPT values are specified, the second one results in this error:

> >     501 Duplicate ORCPT parameter

### 37.5.66 -d20.1

Show resolving delivery agent: parseaddr()

(useful)

> The `-d20.1` (a.k.a. `-d20`) debugging switch causes sendmail to print each recipient address before it is rewritten by rule sets 3 and 0:

> >     -parseaddr(addr)

> Here, `addr` is the recipient address before it is rewritten and before any aliasing has been performed on it.

> The `-d20.1` debugging switch also causes sendmail to print information about problems that may exist in recipient addresses. If an address contains any control character that is not an isspace(3) character, sendmail prints the following message and skips that address:

> >     parseaddr->bad address

> If an address is empty (that is, if it is composed entirely of an RFC822-style comment), sendmail prints the following and skips that address:

> >     parseaddr->NULL

> After the recipient address has been rewritten by rule sets 3 and 0, and if a delivery agent was successfully selected, sendmail prints the result using the printaddr() routine.

> Note that `-d21` can be used to watch the rule sets parse the address, and `-d24` can be used to watch the resulting tokens being pasted back together.

### 37.5.67 -d21.1

Trace rewriting rules

(useful)

> The `-d21.1` (a.k.a. `-d21`) debugging switch causes sendmail to print each step that it takes in rewriting addresses with rules. The `-d21.1` debugging switch causes output to be produced that is identical to the output produced by the `-bt` command-line switch (see Section 38.1, "Overview"):

> >     rewrite: rule set num   input: addr
> >     rewrite: rule set num returns: addr

> Here, `num` is the rule-set number, and `addr` is, first, the address (workspace) before rewriting and, second, the address after rewriting.

> Because rules are recursive by nature, they can sometimes cause infinite loops (see Section 28.6.2, "Rewrite Once Prefix: $:"). When a rule loops more than 100 times, the following error is issued:

> >     Infinite loop in rule set num, rule rnum

> If the `-d21.1` debugging switch was also invoked the above error is followed by:

> >     workspace: state of rewritten address so far, here

### 37.5.68 -d21.2

Trace $& macros

(useful)

> The `-d21.2` debugging switch tells sendmail to show the current value of any deferred-expansion macro (one that was declared with the `$&` prefix). Each such macro that is encountered in processing a rule prints as:

> >     rewrite: LHS $&char => "value"
> >     rewrite: RHS $&char => "value"

> The `char` is the single-character name of the macro, and the `value` is its current value. If that particular macro lacks a value, it will print as (NULL). The `LHS` refers to the left-hand side of the rule, and the `RHS` corresponds to the right-hand side. Deferred-expansion macros are described in Section 31.5.3, "Use Value as Is with $&".

### 37.5.69 -d21.3

Show subroutine calls

> The `-d21.3` debugging switch causes sendmail to print the rule-set number of each rule set called as a subroutine. Rule sets are called as subroutines by using the `$>` rewrite-operator in the RHS of rules (see Section 28.6.4, "Rewrite Through Another Rule Set: $>set"). The output produced looks like this:

> >     ---callsubr rset

> Here, `rset` is the text that was interpreted as the number of the rule set, rather than the numeric value. If the number in the configuration file was a symbolic name, then that symbolic name is printed. (See Section 28.6.4 for more details about the `$>` rewrite-operator.)

### 37.5.70 -d21.4

Result after rewriting by a rule

> If the LHS of a rule matches the workspace, the workspace is rewritten by the RHS of that rule. The `-d21.4` debugging switch causes sendmail to print the result of a successful rewrite:

> >     rewritten as: addr

> Note that the rewritten address (`addr`) may be the result of rewriting by a subroutine call.

### 37.5.71 -d21.10

Announce failure

> If the LHS of a rule fails to match the workspace, the `-d21.10` debugging switch causes sendmail to print:

> >     --- rule fails

### 37.5.72 -d21.12

Announce success and show LHS

> If the LHS of a rule matches the workspace, the `-d21.12` debugging switch causes sendmail to print:

> >     --- rule matches

> The `-d21.12` debugging switch also causes the LHS of each rule to be printed before it is tried:

> >     ---trying rule: lhs

> Remember that rules are pre-expanded when the configuration file is read. As a consequence, defined macros appear as their values in the `lhs`, rather than in their `$``letter` form.

### 37.5.73 -d21.15

Show $digit replacement

> The `-d21.15` debugging switch causes sendmail to print each replacement that is the result of a `$``digit` rewrite-operator in the RHS:

> >     $digit: hex=token ...

> Here, `$``digit` is followed by one or more `hex``=``token` pairs. The `hex` is the address in memory of the `token`, and the `token` is the token from the LHS that is being copied into the workspace. This output can run to many screens.

### 37.5.74 -d21.35

Show token by token LHS matching

> In addition to the rewriting information shown by the debugging switches mentioned above, the `-d21.35` debugging switch also shows each and every attempt by the LHS to match the workspace. Each comparison is printed like this:

> >     ap=workspace rp=operator

> Here, `ap` (for address part) indicates the token in the workspace that the rule is currently trying to match. The `rp` (for rule part) is the operator or token at this point in the LHS that is trying to match the workspace. Note that the `workspace` is a single token from the workspace, and the `operator` is a single operator or token from the LHS of the current rule. A complete comparison of the LHS to the workspace can produce several lines of output for each rule. This output can be useful for understanding how the pattern-matching algorithm works.

> The `-d21.35` debugging switch also shows the index advancing to the next operator and what the corresponding state of the workspace is at that time.

> >     ADVANCE rp=operator ap=workspace

> This is useful for watching the left-hand side trying to find a match.

### 37.5.75 -d21.36

Trace class matching in the LHS

> The `-d21.36` debugging switch causes sendmail to print the following each time it finds a match for either the `$=` or `$~` class-operator:

> >     CLMATCH

> The `-d21.36` switch also shows how sendmail extends the token in the workspace and tries again, should a match for any operator fail. That is, for all operators (not just `$=` or `$~`), if the workspace contained usa.edu, sendmail would first look up usa, then usa., and finally usa.edu. Each such attempt prints as:

> >     EXTEND rp=operator ap=workspace

> If there is still no match, sendmail has to back up and try a different tack. In the case of usa.edu it would back up to the dot. For example, if it were trying `$=X`, the output would look like this:

> >     BACKUP  rp=$=X, ap=.

### 37.5.76 -d22.1

Trace tokenizing an address: prescan()

(useful)

> Processing of rules requires that all addresses be divided into tokens. The `-d22.1` (a.k.a. `-d22`) debugging switch causes sendmail to print the various steps it takes in tokenizing an address.

> In addition to tokenizing, the prescan() routine also normalizes addresses. That is, it removes RFC822-style comments and recognizes quoted strings. Be aware that rules are also viewed as addresses and processed by prescan() when the configuration file is being read.

> The `-d22.1` debugging switch tells sendmail to complain if the first token in the address it is parsing turns out to be nothing

> >     prescan: null leading token

> This can happen if an address (or rule) contains only RFC822-style comments in parenthesis.

### 37.5.77 -d22.11

Show address before prescan

(useful)

> The `-d22.11` debugging switch causes the address to be printed as it appears before any tokenizing or normalization:

> >     prescan: addr

### 37.5.78 -d22.12

Show address after prescan

(useful)

> The `-d22.12` debugging switch causes the address to be printed as it appears after all tokenizing and normalization:

> >     prescan==> addr

### 37.5.79 -d22.36

Show each token

> The `-d22.36` debugging switch causes each token to be printed when found:

> >     tok=token

### 37.5.80 -d22.101

Trace low-level state machine

> For the purpose of tokenizing, an address is viewed as a stream of characters. The process of tokenizing and normalizing is driven by a state machine that handles the stream one character at a time. For example, if the current character is `@`, sendmail sees that it has found both the start and end of a token and so resets its state to begin looking for a new token. But if the current character is `a` and sendmail is currently gathering a token, it knows that it should continue to gather. The use of a state machine enables sendmail to easily keep track of things such as the nesting level of angle brackets and whether or not a quoted string is present.

> The `-d22.101` debugging switch causes sendmail to output two lines of information. The first shows entry into a state (or continuation of a state):

> >     c=char, s=state;

> Here, char is the current character in the stream of characters that makes up the original address. The `state` is a two-digit octal representation of the current state. The first digit modifies the second and is a 2 (which means that this is a meta-character so don't pass it through), a 4 (which means to break the token at this character), or a 6 (which means both 2 and 4). The second digit indicates the state. The list of states and their meanings are shown in Table 37.9. The semicolon separates this output from the rest of the line that is printed below.

> Table 37.9: States Used by parseaddr() to Tokenize Addresses
> Decimal | Octal | Name | Description
> --- | --- | --- | ---
> 0 | 00 | OPR | A wildcard operator (such as `$*`)
> 1 | 01 | ATM | An atom (text token)
> 2 | 02 | QST | Inside a quoted string
> 3 | 03 | SPC | Chewing up spaces
> 4 | 04 | ONE | Pick up one character
> 5 | 04 | ILL | Illegal character

> The rest of the output produced by the `-d22.101` debugging switch shows the state changing to a new state:

> >     ns=nstate

> Here, `nstate` is the new state number, printed in octal with a leading zero.

> Note that the level `101` in `-d22.101` means that this debugging output is for true experts only.

### 37.5.81 -d24.4

Trace address allocation

> The `-d24.4` debugging switch [5] tells sendmail to print a message upon its entry into the allocaddr() routine:

> > [5] There is no `-d24.1` information.

> >     allocaddr(flags=flags, paddr=paddr)

> Here, the address in `paddr` will be copied into another address (not shown). The `flags` is a hexadecimal representation of the `RF_` flags used by sendmail to communicate with some of its internal routines. The meanings of the bits in these flags are shown in Table 37.10.

> Table 37.10: sendmail's Internal RF_ flags
> Hex | Name | Description
> --- | --- | ---
> 000 | RF_COPYNONE | Don't copy anything
> 001 | RF_SENDERADDR | Set = sender address, otherwise recipient
> 002 | RF_HEADERADDR | Set = header address, otherwise envelope
> 004 | RF_CANONICAL | Strip RFC822 comments
> 008 | RF_ADDDOMAIN | Okay to append a domain
> 010 | RF_COPYPARSE | Copy parsed user and host
> 020 | RF_COPYPADDR | Copy the print address

> If RF_COPYPARSE is set in `flags`, the temporary strings for the host and user in the passed address (not shown) are allocated permanent storage in memory.

### 37.5.82 -d24.5

Trace assembly of tokens

> The `-d24.5` debugging switch tells sendmail to print a message upon its entry into the buildaddr() routine.

> >     buildaddr, flags=flags, tv=tokens

> The buildaddr() routine takes an array of separate tokens and pastes them back together again. The `flags` are ORed together hexadecimal values as documented in Table 37.10. The RF_SENDERADDR and RF_HEADERADDR flags tell buildaddr() which rewriting rules to use in processing the address.

> The array of `tokens` being assembled is printed on a single line, each separated from the other by a space.

### 37.5.83 -d24.6

Show result of buildaddr()

> The `-d24.6` debugging switch tells sendmail to print the result of buildaddr()'s attempt to reconstruct an address.

> >     buildaddr => output of printaddr() here (see Section 37.3.1)

### 37.5.84 -d25.1

Trace "sendtolist"

(useful)

> Each recipient address for a mail message is added one-by-one to an internal list of recipients. The `-d25.1` (a.k.a. `-d25`) debugging switch causes sendmail to print each address as it is added to this list:

> >     sendto: list
> >        ctladdr= output of printaddr() here (see Section 37.3.1)

> After each is added, those that have selected a delivery agent with the `F=A` (see Section 30.8.12, F=A) and `F=w` (see Section 30.8.43, F=w) flags set are further processed by aliasing and by reading the user's ~/.forward file. Each new address that results from this processing is added to the list, and any duplicates are discarded.

### 37.5.85 -d26.1

Trace recipient queueing

(useful)

> The `-d26.1` (a.k.a. `-d26`) debugging switch causes sendmail to print the addresses of recipients as they are added to the send queue - an internal list of addresses that sendmail uses to sort and remove duplicates from the recipient addresses for a mail message.

> On entry to the recipient() routine, the `-d26.1` debugging switch causes sendmail to print the raw address (as it appears before adding it to the send queue):

> >     recipient (level): output of printaddr() here (see Section 37.3.1)

> An address can be the result of alias expansion. Because the process of aliasing (including `:include:` and .forward files) can be recursive, it is possible to get too many alias expansions. The `level` shows the number of alias expansions so far. If that number exceeds MaxAliasRecursion (as hard coded in conf.c as 10), sendmail issues this warning:

> >     aliasing/forwarding loop broken (level aliases deep; MAXRCRSN max)

> Next sendmail compares the new address to others that are already in the send queue. If it finds a duplicate, it prints the following message and skips the new address:

> >     addr in sendq: output of printaddr() here (see Section 37.3.1)

> Here, `addr` is the duplicate address. Information about that address is produced with the printaddr() routine.

### 37.5.86 -d26.8

Trace self destructing addresses

> Certain addresses can "self destruct" because they can cause an endless loop. Consider the address `A`. If `A` is aliased to `B` and `B` is aliased to `A`, `A` is a self-destructive address. The `-d26.8` debugging switch causes sendmail to print the address that is being tested for self-destruction:

> >     testselfdestruct: output of printaddr() here (see Section 37.3.1)

### 37.5.87 -d26.10

Show full send queue in testselfdestruct

> The `-d26.10` debugging switch causes the entire send queue to be printed after the `testselfdestruct` above:

> >     SENDQ:
> >     output of printaddr() here (see Section 37.3.1)
> >     --

### 37.5.88 -d27.1

Trace aliasing

(useful)

> The `-d27.1` (a.k.a. `-d27`) debugging switch causes sendmail to print each step it takes when processing local addresses through aliasing. First, sendmail prints the addresses being aliased:

> >     alias(addr)

> Here, `addr` is the address (usually a local username) that is about to be aliased. Note that it may already be the result of previous aliasing. If the `addr` can be aliased, its transformation is printed as:

> >     addr (host, user) aliased to newaddr

> Here, `addr` is the address before aliasing, and the `newaddr` is the new address that resulted from successful aliasing. The `host` and `user` are the hostname and username from the recipient part of the envelope. If the `addr` cannot be aliased, nothing is printed.

> During initialization, if the aliases database cannot be opened, the `-d27.1` debugging switch causes sendmail to print:

> >     Can't open aliasfile

> Here, `aliasfile` is the full pathname of the aliases(5) file, as declared by the `AliasFile` (`A`) option (see Section 34.8.1, AliasFile (A)) or implied with the service-switch file and the `ServiceSwitchFile` option (see Section 34.8.61).

> If the failure was due to a faulty map declaration, sendmail logs the following error:

> >     setalias: unknown alias class mapclass

> If the map is not one that is allowed to provide alias services, sendmail logs this error:

> >     setalias: map class mapclass can't handle aliases

> If sendmail is trying to create a database file and it can't (usually when it is run with the `-bi` command-line switch or run as newaliases), the `-d27.1` debugging switch causes the following error to be printed:

> >     Can't create database for filename: reason here

> A self-destructive alias can cause a dangerous loop to occur. For example, the following two aliases can lead to a loop on the host mailhost:

> >     jake:           Jake_Bair
> >     Jake_Bair:      jake@mailhost

> The `-d27.1` debugging switch causes the following message to be printed when sendmail tests an address to see whether it loops:

> >     self_reference(addr)
> >             ... no self ref                    if it didn't loop
> >             ... cannot break loop for "addr"   if it's unbreakable

> An alias loop is unbreakable if no local username can be found in the list of aliases.

> The `-d27.1` debugging switch also causes sendmail to print the following message when it is attempting to read the user's ~/.forward file:

> >     forward(user)

> If the user has no home directory listed in the passwd(5) file, sendmail issues the following message with a syslog(3) level of LOG_CRIT:

> >     forward: no home

> The `-d27.1` debugging switch also causes sendmail to print a warning if it cannot open or lock an alias file for automatic rebuilding (see Section 34.8.4, AutoRebuildAliases (D), the `AutoRebuildAliases` (`D`) option):

> >     Can't open file:  reason here
> >     newaliases: cannot open file:  reason here

> Here, the error might be caused by the file simply not existing (as would be the case if it was NSF-mounted on a down host) or an I/O error (as would be the case for a bad disk).

> >     warning: cannot lock file:  reason here

> Failure to lock can be caused by system errors or by the file being read-only. Note that maintaining an aliases file under revision control can cause a read-only copy to exist, resulting in the following error:

> >     Can't create database for file:  reason here
> >     Cannot create database for alias file file

> This error indicates that the output file (the dbm(3) or db(3) file) could not be created or written.

### 37.5.89 -d27.2

Include file, self reference, error on home

(useful)

> The `-d27.2` debugging switch causes each `:include:` and .forward filename to be printed before each is opened for reading:

> >     include(file)

> The `-d27.2` debugging switch also causes additional information to be printed for the alias loop check described above:

> >     self_reference(addr)
> >             ... getpwnam(user)...found     if in passwd file
> >             ... getpwnam(user)...failed     otherwise

> The `-d27.2` debugging switch also causes sendmail to print a message every time it sleeps while waiting for the aliases database to be rebuilt:

> >     aliaswait: sleeping for sec seconds

> Also, when processing the ~/.forward file, sendmail may experience a temporary inability to read it (such as when an NFS server is down). In that case the `-d27.2` debugging switch causes the following message to be printed:

> >     forward: transient error on home

> Here the message will be queued and tried again later.

### 37.5.90 -d27.3

Forwarding path and alias wait

(useful)

> The `-d27.3` debugging switch causes each path for a possible .forward file to be printed before it is tried:

> >     forward: trying file

> Here, file is each file in the path of files declared by the `ForwardPath` (`J`) option (see Section 34.8.27, ForwardPath (J)).

> The `-d27.3` debugging switch also causes sendmail to trace its wait for another alias rebuild to complete (see Section 24.5.1, "Rebuild the Alias Database"). First sendmail prints the class (such as `hash`) and filename for which it will wait:

> >     aliaswait(class:file)

> If the database is not rebuildable (as would be the case with a network map class like nis, nis+, or hesiod), the `-d27.3` debugging switch causes the following to be printed:

> >     aliaswait: not rebuildable

> If the `file` specified doesn't exist, the `-d27.3` debugging switch prints

> >     aliaswait: no source file

> The `-d27.3` debugging switch also causes sendmail to print an error message if there was a read error while processing a `:include:` or .forward file:

> >     include: read error: reason here

### 37.5.91 -d27.4

Print not safe

(useful)

> A ~/.forward file must be owned by the user or by root. If it is not, it is considered unsafe, and sendmail ignores it. The `-d27.4` debugging switch causes sendmail to print a message describing any such file it finds unsafe:

> >     include: not safe (uid=uid)

> Note that a file is considered unsafe if, among other things, it lacks all read permissions.

> The `-d27.4` debugging switch also causes sendmail to print information about a `:include:` file beyond that printed with `-d27.2` above:

> >     include(file)              printed with -d27.2
> >        ruid=ruid euid=euid     printed with -d27.4

> This shows the real userID (`ruid`) and effective userID (`euid`) of the current running sendmail.

> The `-d27.4` debugging switch also causes sendmail to print an error if a `:include:` or ~/.forward file cannot be opened for reading:

> >     include: open: reason here

### 37.5.92 -d27.5

Trace aliasing with printaddr()

> The `-d27.5` debugging switch tells sendmail to print several addresses with printaddr() (see Section 37.3.1) as each one is handled.

> When an address is aliased to another, the original needs to be marked as one that shouldn't be delivered. The `QDONTSEND` below means just that:

> >     alias: QDONTSEND output of printaddr() here (see Section 37.3.1)

> If there was a self-reference, the retained address is printed like this:

> >     sendtolist: QSELFREF output of printaddr() here (see Section 37.3.1)

> If the original (before the test for a self-reference) is not the same as the retained address, the original must be marked for nondelivery:

> >     sendtolist: QDONTSEND output of printaddr() here (see Section 37.3.1)

> If an address resulted from a `:include:` or ~/.forward file, it will have a controlling user associated with it. That controlling user's address needs to be marked for nondelivery:

> >     include: QDONTSEND output of printaddr() here (see Section 37.3.1)

### 37.5.93 -d27.8

Show setting up an alias map

> The `-d27.8` debugging switch tells sendmail to print the string passed to its internal setalias() routine.

> >     setalias(what)

> Here, `what` is one of the items listed with the `AliasFile` (`A`) option (see Section 34.8.1), such as /etc/aliases, or implied with the service-switch file and the `ServiceSwitchFile` option (see Section 34.8.61).

### 37.5.94 -d27.9

Show uid/gid changes with :include: reads

(useful)

> The `-d27.9` debugging switch causes sendmail to trace the setting and resetting of its uid and gid identities when processing `:include:` and ~/.forward files. First an additional line is printed below the output of the `-d27.2` and `-d27.4` debugging switches:

> >     include(file)              printed with -d27.2
> >        ruid=ruid euid=euid     printed with -d27.4
> >     include: old uid = ruid/euid

> The second and third lines above both contain the same information. After the new line is printed, sendmail may or may not change its identity depending on the nature of a `:include:` or ~/.forward file and that file's controlling user. Whether it changed or not, sendmail prints:

> >     include: new uid = ruid/euid

> After sendmail has finished processing a `:include:` or ~/.forward file, it resets its uid and gid back to their original values and displays the result:

> >     include: reset uid = ruid/euid

### 37.5.95 -d27.14

Show controlling user that caused change in identity

> The `-d27.14` debugging switch causes sendmail to print the controlling user's address that led to the changing of the uid and gid or the currently running process:

> >     include(file)                  printed with -d27.2
> >        ruid=ruid euid=euid         printed with -d27.4
> >     ctladdr addr                   output of printaddr() produced with this -d27.14
> >     include: old uid = ruid/euid   printed with -d27.9

> The output of the printaddr() routine is described in Section 37.3.1.

### 37.5.96 -d27.20

Show how alias will be looked up in a map

> The `-d27.20` debugging switch causes sendmail to show how it is about to look up an alias in one of its database maps:

> >     setalias(what)        printed with -d27.8
> >        map class:map what

> Here, `class` is the type of map being looked up, such as hash or implicit (see Section 33.3, "The K Configuration Command"). The `map` is the map name, such as Alias0. The `what` is one of the items listed with the `AliasFile` (`A`) option (see Section 34.8.1), such as /etc/aliases, or implied with the service-switch file and the `ServiceSwitchFile` option (see Section 34.8.61).

### 37.5.97 -d28.1

Trace user database transactions

(useful)

> The sendmail program can be compiled to use the user database (see Section 33.5, "The User Database") by defining USERDB in the Makefile (see Section 18.8.54, USERDB). If an address is selected by rule set 0 for delivery by a delivery agent with the `F=l` flag set, and if it remains unaliased even if the `F=A` flag is set, it is looked up in the user database. The `-d28.1` (a.k.a. `-d28`) debugging switch is used to watch the interaction between sendmail and the user database:

> >     udbexpand(addr)

> Here, addr is the address being looked up.

> The sender is looked up in a similar fashion. The intent in this case is to correct information such as the return address:

> >     udbmatch(login, what)

> Here, `login` is the login name of the sender and `what` is the `mailname` for sender lookups. If the lookup is via hesiod, sendmail will print the same information like this:

> >     hes_udb_get(login, what)

> If the sender is found in the database, sendmail prints:

> >     udbmatch ==> login@defaulthost

> Here, `login` may be a new login name. The `defaulthost` is either the sitewide host for all reply mail as defined in the user database or the default destination host for a particular user.

> In the event that a db(3) style user database fails to open, the `-d28.1` debugging switch displays the following error message:

> >     dbopen(database):  reason for failure here

### 37.5.98 -d28.2

Show no match

> The `-d28.2` debugging switch causes sendmail to print any failures in lookups:

> >     udbmatch: no match on login (length) via method

> This shows that the name `login` was looked up with a particular length, using the database `method`, where `method` is either `db` or `hesiod`.

### 37.5.99 -d28.4

Show result of lookup

> The `-d28.4` debugging switch causes sendmail to print the result of its attempt to open (initialize) each database. There are three possible results:

> 1. If a file on the local machine contains the information sought, sendmail prints

>    >     FETCH: file fname

>    Here, `fname` is the name of the local file.

> 2. If a mail message should be sent to another host for delivery, sendmail prints:

>    >     FORWARD: host hostname

>    Here, `hostname` is the full canonical name of the host that takes delivery.

> 3. An unknown result causes the address to remain unchanged and the following message to be printed:

>    >     UNKNOWN

### 37.5.100 -d28.8

Try hes-getmailhost()

> If sendmail is compiled with HES_GETMAILHOST defined (see Section 18.8.11, HES-GETMAILHOST), the following is printed when the `-d28.8` debugging switch is used:

> >     udbmatch: no match on login (length)   from -d28.2
> >       ... trying hes_getmailhost (login)
> >     udbexpand: hesiod-getmail login stat err

> Here, hes_getmailhost() is called to retrieve the name of the post office that handles this `login`. If that call fails, the last line is printed, showing that the hesiod error `err` occurred.

### 37.5.101 -d28.16

MX records for forward host

> If a lookup is for a forwarding host (FORWARD above) and the forwarding host has MX records, the `-d28.16` debugging switch causes those records to be printed:

> >     getmxrr(host): number
> >         first MX record here
> >         second MX record here
> >         etc.

> Here, `host` is the name of the host to which the lookup is forwarded. The `number` is the number of MX records found. That line is then followed by `number` MX records for that host.

### 37.5.102 -d28.20

Show udb lookup

> The internal udb_map_lookup() routine is called each time anything is looked up in the udb database. Upon entry into that routine, the `-d28.20` debugging switch causes sendmail to print

> >     udb_map_lookup(name, what)

> Here, the `what` is key about to be looked up in the map named `name`. This routine in turn calls udbmatch(). Note that the `-d38.20` debugging switch also produces this output.

### 37.5.103 -d28.80

Preview lookups

> The `-d28.80` debugging switch causes sendmail to show what it is about to lookup.

> >     udbexpand: trying login (length) via method

> This shows that the name `login` was looked up with a particular `length`, using the database `method`, where `method` is either `db` or `hesiod`.

> The `-d28.80` debugging switch also causes the result of a lookup to be displayed:

> >     udbexpand: match login: result

> Here, `login` was found, and the lookup returned `result`.

> The `-d28.80` debugging switch also causes the result of hes_udb_get() to be displayed:

> >     hes_udb_get(login, what)             printed with -d28.1
> >     hes_udb_get => result                printed with -d28.80

> Here, the hesiod library routine hes_resolve(3) is called with the two arguments `login` and `what`. The `result` (a string) is printed on the second line.

### 37.5.104 -d29.1

Special rewrite of local recipient

> With a level 2 or greater configuration file (see the `V` configuration command in Section 27.5, "The V Configuration Command"), V8 sendmail passes the user part (`$u`) of local recipient addresses through rule set 5 as a hook to select a new delivery agent. Rule set 5 is called if the address is unchanged after all aliasing (including the ~/.forward file). The `-d29.1` (a.k.a. `-d29`) debugging switch causes the address to be printed as it appears before the rule set 5 rewrite:

> >     maplocaluser: output of printaddr() here (see Section 37.3.1)

> Information about the address is printed with the printaddr() routine. The output of maplocaluser() becomes the input to recipient(), so the result of rewriting can be seen by using the `-d26.1` debugging switch in combination with this one.

> Note that the particulars about whether or not an address will be processed by rule set 5 are described in `-d29.5` below.

### 37.5.105 -d29.4

Trace fuzzy matching

(useful)

> Fuzzy matching is the attempt to match a local recipient name to one of the names in the gecos field of the passwd(5) file (or NIS map). The `-d29.4` debugging switch causes the process of fuzzy matching to be traced:

> >     finduser(name)

> Here, `name` is an address in the form of a local user address, without the host part. The `name` is first looked up in the passwd(5) file on the assumption that it is a login name. If it is found, sendmail prints

> >     found (non-fuzzy)

> If sendmail was compiled with hesiod support, all numeric login names will not work properly, resulting in the following:

> >     failed (numeric input)

> If the name is looked up and not found, the entire passwd(5) is searched, to see whether `name` appears in any of the gecos fields. This search is done only if MATCHGECOS (see Section 18.8.18, MATCHGECOS) was defined when sendmail was compiled and if the `MatchGECOS` (`G`) option (see Section 34.8.34, MatchGECOS (G)) is true. If MATCHGECOS was undefined, the search ends and the not-found `name` causes the mail to bounce. If the `MatchGecos` (`G`) option is false, sendmail bounces the message and prints the following:

> >     not found (fuzzy disabled)

> If the `MatchGecos` (`G`) option is true, the gecos fields are searched. But before the search starts, any underscore characters (and the character defined by the BlankSub (`B`) option; see Section 34.8.5, BlankSub (B)) that appear in name are converted to spaces. Then, in turn, each gecos field has the full name extracted (everything following the first comma, semicolon, or percent is truncated off, including that character), and any `&` characters found are converted to the login name. The two are then compared in a case-insensitive fashion. If they are identical, sendmail prints:

> >     fuzzy matches gecos

> If all gecos fields are compared and no match is found, sendmail bounces the message and prints the following:

> >     no fuzzy match found

> There is no debugging flag to watch each comparison.

### 37.5.106 -d29.5

Preview rule set 5

> The `-d29.5` debugging switch causes sendmail to print an address just before it is tested to see whether rule set 5 should be called:

> >     recipient: testing local?  cl=level, rr5=addr,

> >                                              output of printaddr() here (see Section 37.3.1)

> For the address to be rewritten, the configuration file version as displayed by `level` must be 2 or more, the address in memory for rule set 5 (shown with `rr5`) must be nonzero, the `flags` in `addr` must not contain QNOTREMOTE, QDONTSEND, QQUEUEUP, or QVERIFIED, and the delivery agent for the address must have the `F=5` flag set.

> The `-d29.5` debugging switch also causes sendmail to display the following if the address is rewritten by rule set 5:

> >     maplocaluser: QDONTSEND output of printaddr() here (see Section 37.3.1)

> Here the printaddr() routine prints the old address that is being canceled.

### 37.5.107 -d29.7

Show over-aliasing fuzzy fallback

> If a fuzzy match causes more than three transformations to occur during aliasing, sendmail emits the following error:

> >     aliasing/forwarding loop for login broken

> Here, `login` is the login name of the recipient that started the suspected runaway aliasing. The `-d29.5` debugging switch also causes sendmail to print that it is trying to fall back to the original login name for delivery:

> >     at trylocaluser login

> Note that this message is printed before the message printed by the `-d26` switch (which shows the testing for a self-destructive addresses).

### 37.5.108 -d30

Trace processing of header

> When sendmail reads a mail message, it first collects (reads) the header portions of that message (everything up to the first blank line) and places the result into a temporary file in the queue directory. While it is processing the header, if the `SaveFromLine` (`f`) option (see Section 34.8.59, SaveFromLine (f)), is false, the UNIX-style "`From` " header is removed, and the important information in it is saved for later use.

> The `-d30.1` (a.k.a. `-d30`) debugging switch causes sendmail to print the following succinct message when it finds the end of the header portion of a mail message:

> >     EOH

> If end-of-headers was caused by a read error or a broken connection, sendmail prints:

> >     collect: premature EOM:  reason for failure here

> If end-of-headers was caused by a `Message:` or `Text:` header, then the rest of the header portion of the message is ignored.

### 37.5.109 -d30.2

Eatfrom

> The `-d30.2` debugging switch first causes sendmail to print its entry into collect():

> >     collect

> Then, when sendmail strips (eats) the UNIX-style, five-character "`From` " header from a mail message, it tries to extract (and save) the date from the header. The `-d30.2` debugging switch causes sendmail to print the `field` portion of the header as it appears before the date is extracted:

> >     eatfrom(field)

> The eatfrom() routine will vanish if NOTUNIX (see Section 18.8.32, NOTUNIX) is defined when compiling sendmail.

### 37.5.110 -d30.3

Show a to-less header being added

> If the header of a mail message lacks recipient information (lacks all of the `To:`, `Cc:`, `Bcc`:, and `Apparently-To:` header lines), then sendmail adds a header as defined by the `NoRecipientAction` option (see Section 34.8.43, NoRecipientAction). The `-d30.3` debugging switch causes sendmail to print which `header` it is adding:

> >     Adding header: recipient

> Here, `header` is the text of the header being saved, and `recipient` is the address of the recipient as taken from the envelope of the message.

### 37.5.111 -d30.35

Trace collect states

> The process of collecting the message header and body over an SMTP connection is driven by a state engine inside sendmail. The `-d30.35` debugging switch causes sendmail to display each state just before it is processed:

> >     top, istate=is, mstate=ms

> Here, `is` is the current input state as described in Table 37.11 and `ms` is the current message state as described in Table 37.12.

> Table 37.11: collect() Input States
> istate | Name | Description
> --- | --- | ---
> 0 | IS_NORM | Currently in middle of a line
> 1 | IS_BOL | Currently at beginning of a line
> 2 | IS_DOT | Just read a dot at beginning of line
> 3 | IS_DOTCR | Just read ".\r" at beginning of line
> 4 | IS_CR | Just read a carriage return

> Table 37.12: collect() Message States
> mstate | Name | Description
> --- | --- | ---
> 0 | MS_UFROM | Currently reading UNIX from line
> 1 | MS_HEADER | Currently reading message header
> 2 | MS_BODY | Currently reading message body

> The `-d30.35` debugging switch also causes the same information to be printed every time sendmail goes to a new state:

> >     nextstate, istate=is, mstate=ms, line = "header"

> Here, the extra information is the current text of the header being processed.

### 37.5.112 -d30.94

Trace collect states

> The `-d30.94` debugging switch causes sendmail to print the input state (see Table 37.11) for each character being processed:

> >     istate=is, c=char (hex)

> Each character is printed both as the character it is (`char`) and how it is represented in hexadecimal (`hex`).

### 37.5.113 -d31.2

Trace processing of headers

(useful)

> Header lines (see Section 35.1, "The H Configuration Command") from the configuration file and from mail messages are processed by the chompheader() routine before they are included in any mail message. That routine parses each header line to save critical information, to check for validity, and to replace default values with new values.

> The `-d31.2` debugging switch [6] shows that sendmail is about to check whether it should replace a `From:` or `Resent-From:` header with the one defined by the `H` configuration command. If the configuration file is not being read and if sendmail is not processing the queue, the following test is made:

> > [6] There is no `-d31.1` information.

> >     comparing header from (header) against default (addr or name)

> The value of the `From:` or `Resent-From:` `header` is compared to the sender's address (`addr`) and to the sender's `name`. If it is that same as either one, the address is replaced.

### 37.5.114 -d31.6

Entering chompheader()

> The `-d31.6` debugging switch shows each header as it appears when it enters the chompheader() routine:

> >     chompheader: line

> Here, line is the exact text of the original header before processing. Unfortunately, there is no debugging switch that allows the result of this processing to be viewed.

> To determine how it should handle a header, sendmail compares each header to its list of headers in sendmail.h. The `-d31.6` debugging switch also shows the result after the comparisons have been done:

> >     no header match

> >     header match, hi_flags= flags in hexadecimal here

> The flags and their hexadecimal equivalence are shown in Table 35.2 in Section 35.5, "Header Behavior in conf.c".

### 37.5.115 -d32.1

Show collected headers

> The `-d32.1` (a.k.a. `-d31`) debugging switch causes sendmail to print the header lines that it collected from a received mail message:

> >     --- collected header ---
> >          header lines here
> >     --------------

> Each header line is printed with the header name on the left, a colon, and the value for that header on the right. If there is no value, sendmail prints <NULL>.

> If the H_DEFAULT flag is set for any header (see Section 35.5.3, "H_DEFAULT"), the value for the header is printed inside parentheses with macros unexpanded, just before it is printed in expanded form. For example,

> >     Full-Name: ($x) Your Full Name

### 37.5.116 -d32.2

Show ARPA mode with setsender

> The `-d32.2` debugging switch works only if the mode set with the `-b` command-line switch is in ARPA (`-ba`) mode (see Section 36.7.3, -ba). It shows the sender address being extracted from the header with setsender():

> >     eatheader: setsender(*value == realvalue)

> The setsender() routine can be further traced with the `-d45.1` debugging switch.

### 37.5.117 -d33.1

Watch crackaddr()

> The crackaddr() routine's job is to find an email address amidst other nonaddress text, then to save that nonaddress part:

> >     gw@wash.dc.gov (George Washington)   crackaddr()  $g (George Washington)

> The `-d33.1` (a.k.a. `33`) debugging switch causes sendmail to print the potential address prior to cracking and, after that, the address that it found:

> >     crackaddr(potential)
> >     crackaddr=>`addr'

> The legal ways that addresses can be placed within other text is described in Section 35.3, "Header Field Contents". See also the `/parse` rule-testing command (Section 38.5.5, "Parse an Address with /parse") to put `crackaddr`() in context.

### 37.5.118 -d34.1

Watch header assembly for output

> The sendmail program uses putheader() to create headers that didn't exist before. The `-d34.1` (a.k.a. `-d34`) debugging switch causes sendmail to print the following on entry to that routine:

> >     -- putheader, mailer = agent --

> Here, `agent` is the symbolic name of the delivery agent that will deliver the bounced message.

### 37.5.119 -d34.11

Trace header generation and skipping

(useful)

> Each header line created is displayed with two leading spaces. For example,

> >     -- putheader, mailer = *file* --
> >       Return-Path: you

> Then certain headers are excluded from the bounced mail message header. Those with the H_CTE flag set (see Section 35.5.12, "H_CTE") and either the MCIF_CVT8TO7 or MCIF_INMIME mci flags set (see Table 37.17) will have the text:

> >     (skipped (content-transfer-encoding))

> appended and that header skipped (excluded).

> Any header that has both H_CHECK and H_ACHECK flags set and doesn't have identical delivery agent flags set for itself and its cached connection information will also be skipped:

> >     (skipped)

> All resent headers (those marked with H_RESENT) are also skipped:

> >     (skipped (resent))

> Return-receipt headers are also skipped:

> >     (skipped (receipt))

> If a `Bcc:` header (see Section 35.10.4, Bcc:) is being skipped, this is printed:

> >     (skipped - bcc)

> Finally, valueless headers are also skipped with this message:

> >     (skipped - null value)

> Any headers that survive this skipping process are included in the eventually delivered bounced message. Note that MIME headers are not generated or displayed here (see -d43).

### 37.5.120 -d35.9

Macro values defined

(useful)

> The `-d35.9` debugging switch [7] causes sendmail to print each macro as it is defined. The output looks like this:

> > [7] There is no `-d35.1` information.

> >     define(name as "value")

> Here, the `name` is the macro's name, and the value is the value (text) assigned to the macro. If the macro already has a value assigned to it, sendmail prints:

> >     redefine(name as "value")

### 37.5.121 -d35.14

Macro Identification

> With the introduction of multicharacter macro names, it is now necessary for sendmail to convert each macro name from text form into sendmail's internal form. Single-character macro names are represented by themselves. Multicharacter names are represented by values from 0240 (octal) upward. The `-d35.14` debugging switch causes sendmail to print each macro name as it is being looked up:

> >     macid(name) => value

> The `name` is the text immediately following a `$` character, including any trailing junk in the line. For example, the following miniconfigurations file:

> >     V7
> >     D{FOO}foo
> >     R$H     ${FOO}  note no $H defined

> produces this output (with only the `macid` lines shown):

> >     macid({FOO}foo) => 0xa0
> >     macid(H\t${FOO}\tnote no $H defined) => H
> >     macid({FOO}\tnote no $H defined) => 0xa0
> >     macid(H defined) => H

### 37.5.122 -d35.24

Macro expansion

> Macros that are included in text must be translated into values (expanded) so that the values may be used. The `-d35.24` debugging switch tells sendmail to display such text both before and after the macros in it have been expanded. The "before" looks like this:

> >     expand("text")

> For example,

> >     expand("$w.$D")

> The text (here `$w.$D`) may be any ASCII string. In it, special characters like the newline character are printed in C language, backslash-escaped notation (such as `\n`). Macros are printed with either the `$` prefix (such as `$w` above with V8 sendmail) or some other prefix (IDA uses `^Aw.^AD`, SunOS uses `/w./D`; others use the archaic `\001w.\001D` notation).

> Expansion is performed only on defined macros (using the `$` prefix), on macro conditionals (in which one of two values is used, depending on whether a macro has a value or not, such as `$?x$x$|nobody$.`), and and on the `$&` prefix (deferred expansion).

> After the first (leftmost) macro or conditional is expanded in text, sendmail prints the transformed text as follows:

> >     expanded ==> "text"

> For example,

> >     expanded ==> "wash.$D"

> If any unexpanded macros or conditionals remain in text, this `expanded` process is recursively repeated until everything that can be expanded has been expanded. This process of recursion allows macros to have other macros as their values.

### 37.5.123 -d36.5

Trace processing by stab()

> The symbol table is a block of memory that contains information about all the symbolic names used by sendmail. Symbolic names are delivery agent names (such as `local`), aliases, database classes, hostnames, and macros. Symbols are placed into the symbol table with the stab() routine. That routine is also used to see whether a symbol has already been inserted and, if so, to obtain its value. The `-d36.5` debugging switch [8] causes sendmail to print the following upon its entry into the stab() routine:

> > [8] There is no `-d36.1` information.

> >     STAB: name type

> Here, `name` is the symbolic name to be inserted or looked up. The `type` is one of the values listed in Table 37.13.

> Table 37.13: Types of Symbols Recognized by stab()
> Type | Mnemonic | Description
> --- | --- | ---
> 0 | ST_UNDEF | Undefined type
> 1 | ST_CLASS | Class (from `C` and `F` configuration commands)
> 2 | ST_ADDRESS | An address in parsed format
> 3 | ST_MAILER | A delivery agent (from `M` configuration command)
> 4 | ST_ALIAS | An alias, if no external database
> 5 | ST_MAPCLASS | A database class (`K` command)
> 6 | ST_MAP | Function that handles a class
> 7 | ST_HOSTSIG | Host MX signature
> 8 | ST_NAMECANON | Cached canonical name
> 9 | ST_MACRO | Macro name to id value mapping
> 10 | ST_RULESET | Ruleset name to number mapping
> 11 | ST_SERVICE | Service switch file entry
> 16 | ST_MCI | SMTP connection status\*[=a]

> This is the base (offset) of types 16 through 16+n, where n is 16 plus MAXMAILERS as defined in conf.h. If stab() is being used to insert a symbol, the above output is concluded with:

> >     entered

> If stab() is being used to look up a symbol, one of the two following messages is printed:

> >     not found
> >     type type val hex hex hex hex

> If it is found, four hexadecimal values are printed, which show the first four 4-byte words of the value.

### 37.5.124 -d36.9

Show hash bucket

> A hashing algorithm is used to make the symbol table more efficient. The `-d36.9` debugging switch is used to see the hash value selected for any given symbol:

> >     (hfunc=hash)

> The number of possible hash-table buckets is limited by STABSIZE, as defined in stab.c. [9]

> > [9] You can experiment with different hashing algorithms by modifying the code in stab.c. But note that it has already been heavily tuned in V8.7, roughly doubling its speed over that of earlier versions.

### 37.5.125 -d36.90

Trace function applied to all symbols

> The `-d36.90` debugging switch causes the name and type of each symbol to be printed as a common function is applied to each with sendmail's internal stabapply() function.

> >     stabapply: trying type/name

> The stabapply() routine is used to initialize maps and to print the members of a class.

### 37.5.126 -d37.1

Trace setting of options

(useful)

> Options can be set on the command line or in the configuration file. The `-d37.1` (a.k.a. `-d37`) debugging switch allows you to watch each option being defined. As each is processed, this message is first printed, without a trailing newline:

> >     setoption: name (char).sub=val

> Here, `name` is the option's multicharacter name, `char` is its single-character equivalent (or a hexadecimal value if it is non-ASCII), and `sub` is the subvalue for that option if there was one. Finally, val is the value being given to that option. If the option has already been set from the command line and is thus prohibited from being set in the configuration file, sendmail prints:

> >     (ignored)

> A newline is then printed, and the job is done. If defining the option is permitted, sendmail next checks to see whether it is safe. If it is not, sendmail prints:

> >     (unsafe)

> If it is unsafe, sendmail checks to see whether it should relinquish its root privilege. If so, it prints:

> >     (Resetting uid)

> A newline is then printed, and the option has been defined. Options in general and safe versus unsafe are covered in Chapter 34, Options.

### 37.5.127 -d37.8

Trace adding of words to a class

(useful)

> The adding of words to a class (`C` or `F` configuration commands) can be traced with the `-d37.8` debugging switch. Each word is printed like this:

> >     setclass(name, text)

> The `text` is added to the class whose symbolic name is `name`. Class names can be single-character or multicharacter (see Section 32.1, "Class Configuration Commands").

### 37.5.128 -d38.2

Show map opens and failures

(useful)

> Most maps are declared directly with the `K` configuration command (see Section 33.3). Others are declared internally by sendmail, such as the host and alias maps. The `-d38.2` debugging switch [10] first shows maps being initialized:

> > [10] There is no `-d38.1` information.

> >     map_init(class:name, file, pass)

> Here, `class` is one of the internal classes allowed by sendmail, such as host, and dequote (see Section 33.3, the `K` configuration command). The `name` is either the name you gave to the map with the `K` configuration command or one assigned internally by sendmail (like aliases.files). The `file` is either NULL or the name of the database file (such as /etc/aliases). And `pass` is a flag that tells sendmail whether or not it should open the database, rebuild the database, or do neither.

> Next the `-d38.2` debugging switch causes sendmail to show each map as it is about to be opened. The output that is produced will look like one of the following lines:

> >     bt_map_open(name, file, mode)
> >     hash_map_open(name, file, mode)
> >     hes_map_open(name, file, mode)
> >     impl_map_open(name, file, mode)
> >     ldap_map_open(name, mode)
> >     ndbm_map_open(name, file, mode)
> >     ni_map_open(name, file, mode)
> >     nis_map_open(name, file, mode)
> >     nisplus_map_open(name, file, mode)
> >     stab_map_open(name, file, mode)
> >     switch_map_open(name, file, mode)
> >     text_map_open(name, file, mode)
> >     user_map_open(name, mode)

> In all of the previous lines, the `mode` is a decimal representation of the file permissions that are used during the open. The name prefixing each line corresponds to the class of map. For example, `impl` corresponds to the implicit class.

> The `-d38.2` debugging switch also causes sendmail to display the nis domain that was used if one was specified for the nisplus class:

> >     nisplus_map_open(file): using domain ypdomain

> The `-d38.2` debugging switch also allows other silent errors to be printed about some open failures. Under nis+, lookups are performed by named columns (as in the case of the password database, the columns are named `passwd`, `shell`, and so on):

> >     nisplus_map_open(name): can not find key column colname
> >     nisplus_map_open(name): can not find column colname

> Text files that are used as maps must be declared with a filename that is an absolute path (begins with a `/` character thus forming a fully qualified pathname), that exists, and that is a regular file. If there is a problem, one of the following is logged (even if `-d38.2` is not specified):

> >     text_map_open: file name required
> >     text_map_open(file): file name must be fully qualified
> >     text_map_open(name): can not stat file
> >     text_map_open(name): file is not a file

> Text files should be syntactically correct. The delimiting character, `char`, will print either as a single character or as the phrase `(whitespace)`. Note that the third line below will be reported only when the `-d38.2` debugging switch is used:

> >     text_map_open(file): -k should specify a number, not badtext
> >     text_map_open(file): -v should specify a number, not badtext
> >     text_map_open(file): delimiter = char

### 37.5.129 -d38.3

Show passes

> The sendmail program initializes maps in passes so that it can open a map for reading or rebuild. That is, pass 0 opens it for reading only, and passes 1 and 2 open it for updating. This gives sendmail the opportunity to detect optional maps. The `-d38.3` debugging switch causes sendmail to print `wrong pass` every time it skips rebuilding because the pass is inappropriate:

> >     map_init(class:name, file, pass)   from -d38.2
> >     wrong pass

> The `-d38.3` debugging switch also causes sendmail to print a failure message if an `implicit` class map does not exist:

> >     impl_map_open(name, file, mode)    from -d38.2
> >     no map file

### 37.5.130 -d38.4

Show result of map open

(useful)

> When rebuilding the aliases files, each database is opened before it is rebuilt or not. The `-d38.4` debugging switch shows the success or failure of each open:

> >     map_init(class:name, file, pass)   from -d38.2
> >          class:name file valid or invalid

> The status is `valid` if the open succeeded; otherwise, it is `invalid`.

> The `-d38.4` debugging switch also shows each map being looked up in a `switch` class map (see Section 33.8.17, switch).

> >     switch_map_open(name, file, mode)   from -d38.2
> >             map_stack[index] = class:name

> If the `name` is not one that was declared in a `K` configuration command, the following error is printed:

> >     Switch map class: unknown member map name

### 37.5.131 -d38.9

Trace map closings and appends

> The `-d38.9` debugging switch traces map closures for those kind of maps that can be closed:

> >     ndbm_map_close(name, file, flags)
> >     db_map_close(name, file, flags)
> >     impl_map_close(name, file, flags)
> >     prog_map_lookup(name) failed (errno) - closing
> >     seq_map_close(name)

> Here, the `name` is either the name you gave to the map with the `K` configuration command or one assigned internally by sendmail (like aliases.files). The `file` is the filename on disk that contains the database. The `flags` describe the specific features of a map. They are printed in hexadecimal, and the meanings of the values printed are listed in Table 37.14.

> Table 37.14: Flags Describing Properties of Database Maps
> Hex | Text | Description
> --- | --- | ---
> `00001` | MF_VALID | This entry is valid.
> `00002` | MF_INCLNULL | Include null byte in key.
> `00004` | MF_OPTIONAL | Don't complain if map not found.
> `00008` | MF_NOFOLDCASE | Don't fold case in keys.
> `00010` | MF_MATCHONLY | Don't use the map value.
> `00020` | MF_OPEN | This entry is open.
> `00040` | MF_WRITABLE | Open for writing.
> `00080` | MF_ALIAS | This is an alias file.
> `00100` | MF_TRY0NULL | Try with no null byte.
> `00200` | MF_TRY1NULL | Try with the null byte.
> `00400` | MF_LOCKED | This map is currently locked.
> `00800` | MF_ALIASWAIT | Alias map in aliaswait state.
> `01000` | MF_IMPL_HASH | Implicit: underlying hash database.
> `02000` | MF_IMPL_NDBM | Implicit: underlying ndbm database.
> `04000` | MF_UNSAFEDB | This map is world writable.
> `08000` | MF_APPEND | Append new entry on rebuild.
> `10000` | MF_KEEPQUOTES | Don't dequote key before lookup.

> In addition to tracing map closures, the `-d38.9` debugging switch traces map appends allowed by the MF_APPEND flag (see Section 33.3.4.1, "-A append values for duplicate keys (V8.7 and above)") as specified when the database is declared by the `K` configuration command:

> >     ndbm_map_store append=new
> >     db_map_store append=new

> Here `new` is new value appended to the old. Since this property is used for alias files, the new and old values have a comma inserted between them.

### 37.5.132 -d38.10

Trace NIS search for @:@

> The NIS alias map needs to contain a `@:@` entry to indicate that it is fully updated and ready for reading. But because HP-UX omits the `@:@`, it is useful only as a check to see whether the NIS map exists. The `-d38.10` debugging switch causes the result of this check to be printed as:

> >     nis_map_open: yp_match(@, domain, nismap)

> Here, `domain` is the NIS domain, and `nismap` is usually mail.aliases (but it can be redefined in your configuration file; see Section 34.8.1). If the map is not marked as optional (see Section 33.3.4.8, "-o the database file is optional (V8.1 and above)"), the following error will be printed:

> >     Cannot bind to map nismap in domain domain:  reason here

> The `-d38.10` debugging switch also traces the NIS+ open's check for a valid table.

> >     nisplus_map_open: nisplusmap.domain is not a table

> Essentially, this says that the NIS+ map `nisplusmap` (in the domain shown) does not exist. The error is printed even if the `-o` (optional) database switch (see Section 33.3.4.8) is missing.

### 37.5.133 -d38.12

Trace map stores

> The `-d38.12` debugging switch shows values being stored in maps that support updates.

> >     db_map_store(name, key, value)
> >     ndbm_map_store(name, key, value)
> >     seq_map_store(name, key, value)

> Here, the `name` is either the name you gave to the map with the `K` configuration command or the `name` assigned internally by sendmail (like aliases.files). The `key` is the key for which the new value is being stored, and the `value` is the value for that key.

### 37.5.134 -d38.19

Trace switch map finds

(useful)

> A switched map is one that, either as the result of a service-switch file or because of sendmail's internal logic, causes lookups to follow a select path. For example, Sun's Solaris 2 nsswitch.conf might specify that aliases be looked up in the order files, then nis:

> >     switch_map_open(name, file, mode)   from -d38.2
> >     switch_map_find => nmaps
> >                     maptype
> >                     ...

> First the number of maps found is printed with `nmaps`, then each type of map found in the list is printed. Each is a class name, such as files, or nis.

### 37.5.135 -d38.20

Trace map lookups

(useful)

> The -d38.20 debugging switch traces many different map lookups. The getcanonname() routine looks up a hostname and tries to canonify it:

> >     getcanonname(host), trying maptype
> >     getcanonname(host), found
> >     getcanonname(host), failed, stat=error

> Here, `host` is the hostname that is being looked up, and `maptype` is one of files, nis, nisplus, dns, or netinfo. If the canonical name is not found, the `error` shows one of the errors listed in <sysexits.h>. The process of canonifying the name is handled by calling special subroutines based on the `maptype`:

> >     text_getcanonname(host)				 maptype is files
> >     nis_getcanonname(host)				 maptype is nis
> >     nisplus_getcanoname(host), qbuf=query		 maptype is nisplus
> >     dns_getcanonname(host, flag)			 maptype is dns, printed with -d8.2
> >     ni_getcanonname(host)				 maptype is netinfo

> The nisplus_getcanoname() routine is far more verbose than the other. In addition to the information printed above, the `-d38.20` switch also prints

> >     nisplus_getcanoname(host), got count entries, all but first ignored
> >     nisplus_getcanoname(host), found in directory "nisdir"
> >     nisplus_getcanonname(host), found result
> >     nisplus_getcanonname(host), failed, status=nsistatus, nsw_stat=errno

> The -d38.20 debugging switch also traces general lookups in various kinds of databases. Again note that nisplus is more verbose than the others:

> >     ndbm_map_lookup(name, key)
> >     db_map_lookup(name, key)
> >     nis_map_lookup(name, key)
> >     nisplus_map_lookup(name, key)
> >     qbuf=query
> >     nisplus_map_lookup(key), got count entries, additional entries ignored
> >     nisplus_map_lookup(key), found value
> >     nisplus_map_lookup(key), failed
> >     hes_map_lookup(name, key)
> >     ni_map_lookup(name, key)
> >     stab_lookup(name, key)
> >     impl_map_lookup(name, key)
> >     user_map_lookup(name, key)
> >     prog_map_lookup(name, key)
> >     prog_map_lookup(name): empty answer
> >     seq_map_lookup(name, key)

> Here, the `name` is either the name you gave to the map with the `K` configuration command or one assigned internally by sendmail (such as aliases.files). The `key` is the item being looked up. The `file` is the pathname of the file that contains the database.

### 37.5.136 -d38.44

Show nis-getcanonname() record

> The `-d38.20` debugging switch described above prints the nis lookup of the canonical hostname. This `-d38.44` debugging switch prints the result of that lookup:

> >     nis_getcanonname(host)           from -d38.20
> >     got record `result\'

### 37.5.137 -d39.1

Display %digit database mapping

> When the RHS of a rule matches an entry in a database map with `$(` and `$)`, that entry replaces the key. If the entry contains `%``digit` literals, they are replaced by corresponding `$@` values in the RHS (see Section 33.4.2, "Specify Numbered Substitution with $@").

> The `-d39.1` (a.k.a. `-d39`) debugging switch causes sendmail to print the entry and any replacement values:

> >     map_rewrite(entry), av =
> >            value1
> >            value2
> >            ...etc

> After the RHS is rewritten (after all the `$@` values have replaced all the `%``digit` literals), sendmail prints the result:

> >     map_rewrite => rewritten RHS here

### 37.5.138 -d40.1

Trace processing of the queue

> The `-d40.1` (a.k.a. `-d40`) debugging switch traces the placing of a mail message into the queue and the processing of queued files.

> When a mail message is placed into the queue, its `qf` file is written as a `tf` temporary file; then that temporary file is closed and renamed to be the `qf` file. The `-d40.1` debugging switch causes sendmail to announce that it is beginning that process by printing the queued message's identifier:

> >     >>>>> queueing qid(new id) >>>>>
> >     queueing  for each recipient, output of printaddr() here (see Section 37.3.1)
> >     <<<<< done queueing qid <<<<<

> First, the queue identifier is printed (`qid`). If this identifier is brand-new, the phrase "`(new id)`" is printed. Next, sendmail prints complete information about each recipient for the message using the printaddr() routine. Finally, `done queueing` is printed, and the queuing of the `qid` item is finished.

> When sendmail processes files in the queue, it first prereads all the `qf` files and sorts the jobs by priority. After the list has been sorted, the `-d40.1` debugging switch causes sendmail to print that list, one message per line, in the following format:

> >     qfname: pri=priority

> Here, `qfname` is the basename of the `qf` file, and `priority` is the current priority of each message (see Section 34.8.53, RecipientFactor (y)). After the sorted list of messages has been processed, and if there are any messages in that list, sendmail attempts to deliver each of the messages in the order in which it appears in the list. The `-d40.1` debugging switch causes sendmail to print the following line of information for each message processed:

> >     dowork: (qfname)

### 37.5.139 -d40.3

Show envelope flags

> The `-d40.3` debugging switch causes the envelope flags for each message to be printed as it is queued:

> >     >>>>> queueing qid(new id) >>>>>  from -d40.1
> >       e_flags=  output of printenvflags() here

> The envelope flags are described in Table 37.3 in Section 37.5.12.

### 37.5.140 -d40.4

Show qf file lines as they are read

> The `qf` file is composed of individual lines of information (see Section 23.9.11, P line). The `-d40.4` debugging switch causes sendmail to print each of those lines as it is read:

> >     +++++ Xtext

> Each line begins with five plus characters. The `qf` file's key letter (here, `X`) follows, then the rest of the `text` that made up that line. In the `qf` file, indented lines (lines that begin with a space or tab character) that immediately follow the key line are appended to that key line. Those joined lines are printed after they are joined. Note that the lines of the `qf` file are printed before they are processed by sendmail. An error in a line is printed after the line is printed.

> If the queue file could not be read, the `-d40.4` debugging switch instead causes sendmail to print this error:

> >     readqf(qid) failed

> Here, `qid` is the queue identifier for the message. Note that reading can legitimately fail if the queue file is locked. Use `-d40.8` (described below) to see the exact reason for failure.

### 37.5.141 -d40.8

Show reasons for failure

> The `-d40.8` debugging switch causes sendmail to print the reason it could not process a message's `qf` file. One possibility is:

> >     readqf(qfname): fopen failure (error text here)

> If the failure was caused by anything other than the file's nonexistence, the following is also logged:

> >     readqf: no control file qfname

> If the `qf` file could not be read because it is locked by another incantation of sendmail (a valid reason), the `-d40.8` debugging switch prints:

> >     qid: locked

> Here, `qid` is the identifier portion of the `qf` file. If the log level is set to greater than 19 (see the `LogLevel` (`L`) option, Section 34.8.33, LogLevel (L)), the above message will also be logged.

> For security the sendmail program fstat(2)'s the `qf` file after it is open to make sure it cannot be fooled by a race condition. If that fstat(2) fails, the following is printed if the `-d40.8` debugging switch was specified:

> >     readqf(qid): fstat failure (error text here)

> If the `qf` file is owned by someone other than the effective uid of sendmail, the `qf` file will be renamed into a `Qf` file (see Section 23.3, "A Bogus qf File (V8 only): Qf"). If this `-d40.8` debugging switch was specified, the following message will also be printed:

> >     readqf(qid): bogus file

> The `MinQueueAge` option (see Section 34.8.41, MinQueueAge) determines the interval between queue runs for any given file. If a `qf` file was not last run at least `MinQueueAge` minutes ago, it is skipped and the `-d40.8` debugging switch causes the following message to be printed:

> >     qid: too young (howlong)

> If the log level is set to greater than 19 (see the `LogLevel` (`L`) option, Section 34.8.33), the above message will also be logged.

### 37.5.142 -d40.9

Show qf and lock file descriptors

> After sendmail has opened the `qf` file (with `-d40.1`) and printed the envelope flags (with `-d40.3`), this `-d40.9` debugging switch will cause the file descriptors for the `qf` file and its corresponding lock file to be dumped:

> >     >>>>> queueing qid(new id) >>>>>  from -d40.1
> >      e_flags=                        from -d40.3
> >      tfp=  output of dumpfd() here
> >      lockfp=  output of dumpfd() here

> The `e_flags` are described in Table 37.3 of Section 37.5.12. Here, `tfp=` shows the file descriptors for the `qf` file, and `lockfp=` shows the descriptors for the lock. See `-d2.9` (Section 37.5.13) for a description of output of dumpfd().

### 37.5.143 -d40.32

Dump the send queue

> The `-d40.32` debugging switch causes sendmail to dump the list of message recipients:

> >     >>>>> queueing qid(new id) >>>>>  from -d40.1
> >       e_flags=                        from -d40.3
> >       sendq=  output of printaddr()) here (see Section 37.3.1)
> >       tfp=                            from -d40.9
> >       lockfp=                         from -d40.9

### 37.5.144 -d41.1

Trace queue ordering

(useful)

> The `-d41` (a.k.a. `-d41`) debugging switch causes sendmail to print its ordering of the queue. First it prints

> >     orderq:
> >             QueueLimitId = qid             if -qI used
> >             QueueLimitSender = sid         if -qS used
> >             QueueLimitRecipient = rid      if -qR used

> See Section 23.6.2.3, "Process by identifier/recipient/sender: -q[ISR]" for an explanation of how the `-qI`, `-qS`, and `-qR` command-line switches can limit the scope of a queue run. If none of them were specified, only `orderq:` is printed. The `-d41.1` debugging switch is extremely handy for previewing the effect of the `-qI`, `-qS`, and `-qR` command-line switches. When combined with `-bp` (mailq), these switches limit the queue listing and thus preview the effect of a limited queue run:

> >     % mailq
> >                     Mail Queue (1 request)
> >     -Q-ID- -Size- ---Q-Time--- ------Sender/Recipient------
> >     MAA11111     4560 Tue Dec 31 12:37 you
> >                                        you@here.us.edu
> >     % mailq -d41.1 -qI22222
> >     orderq:
> >             QueueLimitId = 22222
> >     Mail queue is empty

> The `-d41.1` debugging switch also traces the growth of the queue working list. Every time the limit of that list is reached, the internal routine grow_wlist() is called to extend the list size by QUEUESEGSIZE (where QUEUESEGSIZE is described in Section 18.8.38, QUEUESEGSIZE).

> >     grow_wlist: WorkListSize=current
> >     grow_wlist: WorkListSize now newsize

> If the log level is set to greater than 1 (see the `LogLevel` (`L`) option, Section 34.8.33), the following is also logged each time the list size grows:

> >     grew WorkList for qdirectory to newsize

> If the size could not be increased (because the program reached the limit of available memory) and if the `LogLevel` (`L`) option is greater than 0, sendmail will log this error at LOG_ALERT:

> >     FAILED to grow WorkList for qdirectory to newsize

> This message will repeat until there are no more queue entries to process after the limit is received. However, all the files that are already in the work list will be processed, so presumably the next run will catch the failed messages.

### 37.5.145 -d41.2

Cannot open qf

> Ordinarily, sendmail is silent about failures to open a `qf` file, but the `-d41.2` debugging switch causes it to print the reason the open failed:

> >     orderq: cannot open qfname (reason for failure here)

> Here, `qfname` is the name of the `qf` file that could not be opened.

### 37.5.146 -d41.49

Show excluded (skipped) queue files

> The `41.49` debugging switch causes sendmail to display the queue files that were not included in the work list:

> >     skipping qfname (bit)

> Here, the `bit` is a hexadecimal representation of the requirement that was not met. These bits are listed in Table 37.15.

> Table 37.15: Bits Describing a Queue Run's Requirements
> Hex | Mnemonic | Description
> --- | --- | ---
> `1` | NEED_P | Priority must be high enough (required qf file line)
> `2` | NEED_T | Must have been in queue long enough (required qf file line)
> `4` | NEED_R | Match a recipient
> `10` | NEED_S | Match a sender

> Note that nothing will be printed if the message was skipped because its identifier did not match the `-qI` specification.

### 37.5.147 -d41.50

Show every file in the queue

> The sendmail program scans the queue directory looking for all the `qf` files to set up its working list. If a file doesn't start with the letters "qf," it is ordinarily silently skipped. The `-d41.50` debugging switch causes sendmail to display every single file it finds in its queue directory:

> >     orderq: checking file

> The `file` can be a directory, such as `..`, or a regular file, such as a `df` or `qf` file.

### 37.5.148 -d42.2

Show connection checking

> V8 sendmail can be configured with the `ConnectionCacheSize` (`k`) option (see Section 34.8.10, ConnectionCacheSize (k)) to maintain open SMTP connections to a few other hosts. Before making a new SMTP connection, sendmail checks to see if it already has one established. The `-d42.2` [11] debugging switch causes sendmail to print the result of that check.

> > [11] Note that there is no `-d42.1` information.

> >     mci_get(host mailer): mci_state=state, _flags=flag, _exitstat= stat, _errno=err

> Here, the `host` is the name of the host to which the connection is to be made, and the `mailer` is the symbolic name of the delivery agent. The `state` is the status of the current SMTP connection (if there is one) as shown in Table 37.16.

> Table 37.16: mci_get() Connection States
> State | Mnemonic | Description
> --- | --- | ---
> 0 | MCIS_CLOSED | No traffic on this connection
> 1 | MCIS_OPENING | Sending initial protocol
> 2 | MCIS_OPEN | Connection is open
> 3 | MCIS_ACTIVE | Message being sent
> 4 | MCIS_QUITING | Running SMTP quit protocol
> 5 | MCIS_SSD | SMTP service shutting down
> 6 | MCIS_ERROR | I/O error on connection

> The `flag` describes the overall status of the connection. It can have one or more values from those shown in Table 37.17 where those values are OR'd together.

> Table 37.17: mci_get() Status Flags
> Flag | Mnemonic | Description
> --- | --- | ---
> 0x0001 | MCIF_VALID | If set, this entry is valid
> 0x0002 | MCIF_TEMP | If set, don't cache this connection
> 0x0004 | MCIF_CACHED | If set, connection is currently in open cache
> 0x0008 | MCIF_ESMTP | This host speaks ESMTP
> 0x0010 | MCIF_EXPN | EXPN command supported
> 0x0020 | MCIF_SIZE | SIZE option supported
> 0x0040 | MCIF_8BITMIME | BODY=8BITMIME supported
> 0x0080 | MCIF_7BIT | Strip this message to 7 bits
> 0x0100 | MCIF_MULTSTAT | MAIL11V3, handles MULT status
> 0x0200 | MCIF_INHEADER | Currently outputting header
> 0x0400 | MCIF_CVT8TO7 | Convert from 8 to 7 bits
> 0x0800 | MCIF_DSN | DSN extension supported
> 0x1000 | MCIF_8BITOK | Okay to send 8 bit characters
> 0x2000 | MCIF_CVT7TO8 | Convert from 7 to 8 bits
> 0x4000 | MCIF_INMIME | Currently reading MIME header

> The `stat` is the exit status of the last delivered mail message to this connection. It is one of the values defined in <sysexits.h>. The `err` is the value of the last system error (if any), as defined in <errno.h>.

### 37.5.149 -d42.5

Trace caching and uncaching connections

> The `-d42.5` debugging switch shows connections being cached and freed:

> >     mci_cache: caching addr (host) in slot slot
> >     mci_uncache: uncaching addr (host) from slot slot (doquit)

> Here, `addr` is the address in memory of the C language structure (struct mailer_con_info defined in sendmail.h) that defines the current (or about to be made) connection. The `host` is the name of the host to which the connection is to be made. The `slot` is an index into the array of structures that contain the connection information. For uncaching, the `doquit` is a Boolean that tells sendmail to close the connection if it is nonzero.

> The `-d91.100` debugging switch produces information identical to the above but logs its output at LOG_DEBUG instead of printing it:

> >     qid: mci_cache: caching addr (host) in slot slot
> >     qid: mci_uncache: uncaching addr (host) from slot slot (doquit)

> Note that each line is prefixed by the queue identifier for the message (`qid`). The `-d91.100` debugging switch is especially handy for monitoring caching when running sendmail as a daemon.

### 37.5.150 -d43.1

Trace MIME conversions

> V8.7 sendmail can convert 8-bit MIME to 7 bits. The `-d43.1` (a.k.a. `-d43`) debugging switch traces this process.

> >     mime8to7: flags = mflags, boundaries =  boundaries printed here

> Here, the internal mime8to7() routine has been called to do the conversion. The `mflags` are printed in hexadecimal, and are described in Table 37.18.

> Table 37.18: Conversion Flags for mime8to7()
> Hex | Mnemonic | Description
> --- | --- | ---
> 0x00 | M87F_OUTER | This is the outer context
> 0x01 | M87F_NO8BIT | Can't have 8-bit in this section
> 0x02 | M87F_DIGEST | Currently processing a multipart digest

> The `boundaries` is either `<none>` or a list of the boundaries found in the message. In multipart messages the `-d43.1` debugging switch causes each boundary to be printed as it is found:

> >     mime8to7: multi part boundary boundary printed here

### 37.5.151 -d43.3

See the final MIME boundary name

> The `-d43.3` debugging switch is used to see the final MIME boundary name that is selected:

> >     mime8to7=>boundary (multipart)
> >     mime8to7=>boundary (basic)

> Each line is prefixed with three tabs.

> The `-d43.3` debugging switch is also used to trace 7- to 8-bit conversion. If a delivery agent has the `F=9` flag set (see Section 30.8.6, F=9) and if the message has a `Content-Transfer-Encoding:` header that specifies Base64 or Quoted-Printable, sendmail will attempt to convert it from its encoded 7-bit form back into 8-bit form:

> >     mime7to8 => base64 or quoted-printable  to 8bit done

### 37.5.152 -d43.5

Watch search for boundaries

> The `-d43.5` debugging switch allows you to watch the search for boundaries. First each line read is printed:

> >     mimeboundary: line="line is printed here"...

> >                                                           boundary, if found, printed here

> Then, if the line contained a valid MIME boundary, the found boundary is printed at the end of the preceding.

### 37.5.153 -d43.8

Show the calculations

> The sendmail program determines how to convert the MIME message by examining the first eighth of the file. If the first eighth of the total number of characters in the file have the high bit set, conversion will be with Base64; otherwise, it will be with Quoted-Printable (see Section 34.8.22, EightBitMode (8)). If the message is marked as binary, it is always converted with Base64. The `-d43.8` debugging switch causes sendmail to print the result of this calculation:

> >     mime8to7: hcount high bit(s) in bcount byte(s), cte=type

> Here, `cte=` is either `[none]` or the content-transfer-encoding type, such as `binary`.

### 37.5.154 -d43.35

Show boundary lines as emitted

> The `-43.35` debugging switch causes each new boundary line to be printed as it is inserted into the message:

> >     ...-mid-boundary here
> >     ...-end boundary here-

> The midboundary marks begin with a `-`. The ending-boundary mark begins and ends with a `-`.

### 37.5.155 -d43.36

Show content transfer encoding

> The `-43.36` debugging switch causes the encoding header to be printed as it is added to the message:

> >     ...Content-Transfer-Encoding:  type of encoding here

> The type of encoding will either be the original as printed with `cte=` in `-d43.8` above or Base64 or Quoted-Printable.

### 37.5.156 -d43.40

Show parse of Content-Type: header

> The `-43.40` debugging switch causes the contents of the parsed `Content-Type:` header to be displayed.

> >     pvp[n] = "item"

> For zero through `n` items that were parsed, each is printed on its own line.

### 37.5.157 -d43.99

Print the leading/following comments

> The `-d43.99` debugging switch tells sendmail to print each line of MIME commentary that precedes the leading boundary:

> >     ... leading commentary here
> >     ...-midboundary here

> and the commentary that follows the last boundary:

> >     ...-end boundary here-
> >     ... trailing commentary here

### 37.5.158 -d43.100

Mark collect() and putheader()

> The `-d43.100` debugging switch causes sendmail to print a mark just after it has called collect() and after it has called putheader():

> >     +++after collect
> >     +++after putheader

> The collect() routine is traced with the `-d30` debugging switch, and putheader() is traced with the `-d34` debugging switch.

### 37.5.159 -d44.4

Trace safefile()

> The V8 sendmail program tries to be extra careful about file permissions, and the key to checking them is the internal safefile() function. The `-d44.4` debugging switch [12] prints the parameters passed to the safefile() function:

> > [12] There is no `-d44.1` debugging information.

> >     safefile(fname, uid=uid, gid=gid, flags=sff_flags, mode=wantmode)

> Here, the file named `fname` is being checked to determine whether the user identified by the `uid`, with the group `gid`, is allowed to find or use the file. The range of checking is determined by the hexadecimal `sff_flags`, described in Table 37.19. Where a file's permissions are required, the mode printed in `wantmode` will be used.

> Table 37.19: safefile() Access Flags
> Flag | Mnemonic | Description
> --- | --- | ---
> 0x000 | SFF_ANYFILE | No special restrictions
> 0x001 | SFF_MUSTOWN | Uid must own this file
> 0x002 | SFF_NOSLINK | File must not be a symbolic link
> 0x004 | SFF_ROOTOK | Okay for root to own this file
> 0x008 | SFF_RUNASREALUID | If no controlling user, run as real uid
> 0x010 | SFF_NOPATHCHECK | Don't bother checking leading path
> 0x020 | SFF_SETUIDOK | Setuid files are okay
> 0x040 | SFF_CREAT | Okay to create the file if necessary
> 0x080 | SFF_REGONLY | Allow regular files only
> 0x100 | SFF_OPENASROOT | Open as root instead of as uid

> If the SFF_NOPATHCHECK flag is clear (0), sendmail examines each component of the path leading the file. If any component of the path is rejected, the `-d44.4` debugging switch causes sendmail to print:

> >     [dir fname]  reason for the rejection here

> A path component can fail because stat(2) failed. If the `uid` is 0 for root, a warning is logged if a component is found to be group- or world-writable:

> >     WARNING: writable directory fname

> For each component in the path, safefile() checks to verify that this user has permission to search the directory. If the SFF_ROOTOK flag is not set (is clear), root (uid 0) access is special cased in that all directory components must be world-searchable.

> Otherwise, the path component is accepted if it is owned by the `uid` and has the user search bit set or if its group is the same as `gid` and has the group search bit set. If NO_GROUP_SET is undefined when sendmail is compiled (see Section 18.8.31, NO-GROUP-SET) and the `DontInitGroups` option (see Section 34.8.19, DontInitGroups) is not set, each group to which `uid` belongs is also checked. Otherwise, the directory must be world-searchable.

> If the `fname` could not be checked with stat(2), the `-d44.4` debugging switch causes the reason to be printed:

> >      reason for failure here

> If the file does not exist, it may need to be created. If so, sendmail checks to be sure that the `uid` has write permission. The result is printed with the `-d44.4` debugging switch like this:

> >     [final dir fname uid uid mode wantmode]  error here

> If the file exists and if symbolic links are supported, the file is rejected if it is a symbolic link and if the SFF_NOSLINK flag is set. If the `-d44.4` debugging switch is specified, this error is printed:

> >     [slink mode mode]    EPERM

> If the SFF_REGONLY flag is set the file must be a regular file. If it is not, it is rejected, and `-d44.4` causes the following to be printed:

> >     [non-reg mode mode]    EPERM

> If `wantmode` has the write bits set, and the existing file has any execute bits set, the file is rejected and `-d44.4` causes the following to be printed:

> >     [exec bits mode]    EPERM

> If the file has more than one link, the file is rejected and `-d44.4` causes the following to be printed:

> >     [link count nlinks]    EPERM

> If the SFF_SETUIDOK flag is specified, if the file exists, if it has the suid bit set in the mode but no execute bits set in the mode, and if it is not owned by root, sendmail performs subsequent checks under the suid and sgid identities of the existing file. A similar process occurs with the sgid bit. Sendmail then prints:

> >     [uid new_uid, stat filemode, mode wantmode]

> If access is finally allowed, sendmail concludes the above with:

> >     OK

> Otherwise, it concludes with:

> >     EACCES

### 37.5.160 -d44.5

Trace writable()

(useful)

> The `-d44.5` debugging switch displays the values passed to sendmail's internal writable() routine. This routine nearly duplicates the function of the access(3) call [13] but does it much more safely and allows checks to be made under the identity of the controlling user:

> > [13] It is more restrictive for root-owned files and can allow the suid semantics needed for delivery to files.

> >     writable(fname, sff_flags)

> Here, the fname is the full pathname of the file being checked. The `sff_flags` are documented in Table 37.19 above. Success or failure is described under `-d44.4`.

### 37.5.161 -d45.1

Show envelope sender

> The `-d45.1` (a.k.a. `-d45`) debugging switch causes sendmail to print the current form of the envelope sender address before it has fully rewritten that address into its final form:

> >     setsender(addr)

> If the `addr` is empty (as would be the case if the sender were being gathered from the header), sendmail prints NULL. The final envelope sender address is placed into the `$f` macro. (See Section 31.10.14, $f for a description of that macro and the process used by sendmail to set the sender's address.)

### 37.5.162 -d45.3

Show saved domain

> If the `F=C` flag (see Section 30.8.15) is set for the delivery agent selected for the sender, sendmail will save the domain part of the address for later use. The `-d45.3` causes the saved domain part to be printed:

> >     Saving from domain: domain

> The domain is saved in the e_fromdomain part of the C language structure that contains the envelope information for the sender. Later, if the `F=C` flag is set, this domain will be appended to any recipient addresses that lack a domain part.

### 37.5.163 -d45.5

Show don't send to sender

> Unless a message is bounced, it will not be sent to the sender. The `-d45.5` debugging switch causes sendmail to display sender information when this decision is made:

> >     setsender: QDONTSEND  output of printaddr() here (see Section 37.3.1)

### 37.5.164 -d46.9

Show xf file's descriptors

> The `xf` queue file (see Section 23.2.7, "The Transcript File: xf") contains a record of the errors and other information produced by a delivery agent. That information is used for bounced mail. The `-d46.9` debugging switch [14] causes sendmail to dump the file descriptors for the opened `xf` file:

> > [14] There is no `-d46.1` information.

> >     openxscript(xfqid):
> >      output of dumpfd() here (see Section 37.5.13)

> If sendmail cannot open an `xf` file, it logs this warning:

> >     Can't create transcript file xfqid

> It then tries to open /dev/null so that it can continue with the delivery. If that fails, it logs the following panic message and immediately exits:

> >     Can't open /dev/null

> Once the file is open (or not), sendmail turns it into an I/O stream with a call to fdopen(3). If that call fails, sendmail logs this message and immediately exits:

> >     Can't create transcript stream xfqid

### 37.5.165 -d48.2

Trace calls to the check- rule sets

> Beginning with V8.8, sendmail calls rule sets whose names begin with `check_` (see Section 29.10, "The check_... Rule Sets") to filter incoming and outgoing mail. The `-d48.2` debugging switch [15] can be used to display the workspace being passed to each such rule set:

> > [15] There is no `-d48.1` information.

> >     rscheck(name, left, right)

> The `name` is the name of the named rule set being called. If `right` is missing, it prints as NULL, and the workspace passed to the rule set is:

> >     left

> If `right` is present, the workspace is:

> >     left $| right

> Here, the `$|` in the workspace is the `$|` operator.

### 37.5.166 -d49.1

Trace checkcompat()

> The checkcompat() routine inside conf.c can be tuned to solve many problems (see Section 20.1, "How checkcompat() Works"). The default `-d49.1` (a.k.a. `49`) debugging switch inside it prints the arguments that were passed to it:

> >     checkcompat(to=recipient, from=sender)

> When designing your own checkcompat(), you should only use the `-d49` category to trace it.

### 37.5.167 -d50.1

Show envelope being dropped

> Deallocating an envelope frees that envelope's C language structure for future reuse. Deallocation also causes all the queued files for that mail message to be removed (except as possibly prevented by the `-d51` debugging switch described in the next section). An envelope is deallocated after its mail message has been delivered to all recipients (including any failed deliveries).

> The `-d50.1` (a.k.a. `-d50`) debugging switch causes sendmail to print information about each envelope that is being deallocated:

> >     dropenvelope loc id=ident flags=  output of printenvflags() here

> This output shows the address in memory for the envelope's C language structure (`loc`), the queue identifier (`ident`, as used to name queued files), and the envelope flags as printed by printenvflags() (see Table 37.3 in Section 37.5.12).

> Note that if the version of sendmail is pre-8.7, a `Return-Receipt:` header was in the message, and delivery was to at least one local recipient, the process of deallocation also causes acknowledgment of delivery to be returned to the sender and triggers error returns.

> The `-d50.1` debugging switch also shows the `qf` and `df` files just before they are removed:

> >     ===== Dropping [dq]fqid... queueit=bool, e_flags=  output of printenvflags() here

### 37.5.168 -d50.2

Show Booleans

> The `-d50.2` debugging switch shows the setting of three variables that determine how the envelope will be treated:

> >     failure_return=val delay_return=val success_return=val queueit=val

> A 1 indicates that the variable is true, a 0 indicates that it is false.

### 37.5.169 -d50.10

Also show the send queue

> The `-d50.10` debugging switch causes the current send queue to also be printed:

> >     sendq= output of printaddr() here (see Section 37.3.1)

### 37.5.170 -d51.4

Show queue entries being unlocked

> The `-d51.4` [16] debugging switch causes V8 sendmail to print the following each time an envelope is unlocked in the queue:

> > [16] There is no `-d51.1` information.

> >     unlockqueue(qid)

> Here, `qid` is the queue identifier.

### 37.5.171 -d51.104

Prevent unlink of xf file

> The `xf` file (one of the files that form a queued mail message) holds error messages generated by a delivery agent. The last line of text in this file is made the value of the `M` line in the `qf` file (see Section 23.9.9, M line). Ordinarily, the `xf` file is removed after that error line is saved.

> The `-d51.104` debugging switch prevents sendmail from removing the `xf` file. If mail continually fails, this debugging switch can be used to save all error messages instead of just the one that is usually saved in the `qf` file.

### 37.5.172 -d52.1

Show disconnect from controlling TTY

> When sendmail runs as a daemon, it must disconnect itself from the terminal device that is used to run it. This prevents keyboard signals from killing it and prevents it from hanging (on a dial-in line waiting for carrier detect, for example).

> The `-d52.1` (a.k.a. `-d52`) debugging switch shows sendmail disconnecting from the controlling terminal device:

> >     disconnect: In fd Out fd, e=addr

> For both its input and output connections, the `fd` is a decimal representation of the file descriptor number. The `addr` is a hexadecimal representation of the address that contains the envelope information. If the `L` logging level option is greater than 71, sendmail syslog(3)'s the following message to show that it has disconnected:

> >     in background, pid=pid

> Here, `pid` is the process identification number of the child process (the daemon).

### 37.5.173 -d52.100

Prevent disconnect from controlling tty

(useful)

> The `-d52.100` debugging switch [17] prevents sendmail from disconnecting from its controlling terminal device. To show that it is skipping the disconnect, it prints:

> > [17] This was formerly the `-d52.5` debugging switch.

> >     don't

> This debugging switch is useful for debugging the daemon. Note that this `-d52.100` prevents the detach but allows the daemon to fork(2). This differs from the behavior of the `-d99.100` debugging switch.

### 37.5.174 -d53.99

Trace xclose()

> Ordinarily, files are closed silently. The `-d53.99` [18] debugging switch can be used to observe file closings. Just before the file is closed, sendmail prints:

> > [18] There is no `-d53.1` information.

> >     xfclose(fp) what file

> Here, `fp` is the file pointer for the open file, printed in hexadecimal. The `what` is an indication of the internal function that requires the close (such as `savemail` or `mci_uncache`). The `file` is the name of the file to be closed.

> If the close fails, the following is also printed:

> >     xfclose FAILURE: why

> Here, `why` is the text corresponding to the error value returned by fclose(3) (see sys_errlist(3)).

### 37.5.175 -d54.1

Show error return and output message

> The exit values that are returned by sendmail are documented in Section 36.5. The `-d54.1` debugging switch shows the exit value being set by the internal syserr() routine:

> >     syserr: ExitStat = num

> Here, `num` corresponds to the values defined in <sysexits.h>.

### 37.5.176 -d54.8

Show message and flags

> The `-d54.8` debugging switch causes the text of the error message to be printed along with the flags that control its actual output:

> >     -- message (hold) (held)

> If `(hold)` appears, it means that the `message` will be held (stored) and not output. If `(held)` appears, it means that the `message` was previously held and should not be added to the `xf` file. If neither is printed, the `message` will be logged and appended to the `xf` file. If the message on output fails, sendmail will attempt to log this panic message:

> >     qid: SYSERR: putoutmsg (host): error on output channel sending "message": err

> If the message was never queued, the `qid` will print as NOQUEUE. If you are not currently connected to a `host`, it will print as NO-HOST. The `err` is the error that caused the message to fail (as defined in either <sys/errno.h> or sysexits.h).

### 37.5.177 -d55.60

Show file locking

> The sendmail program tries to lock every file before reading or writing it. If sendmail was compiled with HASFLOCK defined (see Section 18.8.9, HAS...), it uses flock(3) to lock and unlock files. If HASFLOCK is not defined, sendmail tries to lock and unlock with fcntl(2).

> The `-d55.60` [19] debugging switch tells sendmail to print how it is about to try to lock a file:

> > [19] There is no `-d55.1` information.

> >     lockfile(filename, action=set, type=l_type)
> >     lockfile(filename, type=what)

> The first form is printed if HASFLOCK is not defined. In it, sendmail is about to use fcntl(2) to lock the file. The action is a decimal representation of the F_SET flag that is fcntl(2)'s second argument. The `l_type` is the l_type structure member of fcntl(2)'s third argument (see the online manual for fcntl(2)).

> The second form is printed if HASFLOCK is defined so that flock(2) will be used. In it, `what` is the type of locking to be performed, printed in octal, as described in Table 37.20.

> Table 37.20: Flags That Control File Locking
> Flag | Mnemonic | Description
> --- | --- | ---
> 001 | LOCK_SH | Make it a shared lock
> 002 | LOCK_EX | Make it an exclusive lock
> 004 | LOCK_NB | Make it a nonblocking lock
> 010 | LOCK_UN | Unlock the file

> For both forms of locking, if the file is successfully locked, the above debugging output is concluded with:

> >     SUCCESS

> Otherwise, it is concluded with:

> >     (error message here) FAILURE

> In this later instance, regardless of the setting of this debugging flag, sendmail will also log the following error message:

> >     cannot lock(filename, fd=num, type=what, omode=octal, euid=euid)

> Here, `lock` is either `lockf` or `flock`. The `filename` and `fd` are the file name and file descriptor for the file. The `what` is the same as described in Table 37.20. If F_GETFL was defined at the system level when sendmail was compiled, then `omode` is an octal representation of the value returned by an fcntl(2) F_GETFL call; otherwise, it is a -1 in octal. The `euid` is the effective uid under which sendmail was running at the time.

### 37.5.178 -d56.1

Persistent host status tracing

> The `-d56.1` (a.k.a. `-d56`) debugging switch tells sendmail to print a record of each step it is going through when saving and updating its persistent host status. The `HostStatusDirectory` option (see Section 34.8.31, HostStatusDirectory) specifies where and whether persistent host status will be saved. Just before a status file is updated, and if the `SingleThreadDelivery` option (see Section 34.8.64, SingleThreadDelivery) is true, it needs to be locked:

> >     mci_lock_host: attempting to lock host

> Here, `host` is the name of the host whose status is being saved or updated. If the hostname is empty (as in the case of an address that contains only an RFC822 comment), one of the following errors is printed for an attempt to lock or unlock the host information:

> >     mci_lock_host: NULL mci
> >     mci_unlock_host: NULL mci

> After the status file is locked, sendmail will transfer the information from that file into its internal mci structure:

> >     mci_load_persistent: Attempting to load persistent information for host

> Again, if the hostname is empty, this error will print:

> >     mci_load_persistent: NULL

> If sendmail was unable to translate the hostname into a UNIX path, the `-d56.1` debugging switch causes it to print:

> >     mci_load_persistent: Couldn't generate host path

> If sendmail was unable open the host status file, it prints:

> >     mci_load_persistent: open(filename): host

> Similarly, when sendmail needs to store or update the host information, it first prints that it is doing so:

> >     mci_store_persistent: Storing information for host

> If sendmail could not open the host status file, it prints:

> >     mci_store_persistent: no statfile

> The internals of the status file are described in Appendix Appendix B, Host Status File Internals.

> Ordinarily, sendmail is silent about its inability to open status files when printing its host information with the hoststat(1) command (see Section 36.1.1, "hoststat (V8.8 and Above)"). But if the `-d56.1` debugging switch is used, sendmail will complain:

> >     mci_print_persistent: cannot open filename: host

> When its host information is being purged with the purgestat(1) command (see Section 36.1.4, "purgestat (V8.8 and Above)"), the `-d56.1` debugging switch tells sendmail to show what it is trying to achieve:

> >     mci_purge_persistent: purging path
> >     mci_purge_persistent: dpurge directory

### 37.5.179 -d56.2

More persistent host status tracing

> The `-d56.2` debugging switch causes sendmail to show additional information about what it is trying to do. Just before attempting to lock a status file, it prints:

> >     mci_lock_host: attempting to lock host

> If a path could not be generated from the hostname, sendmail prints this error:

> >     mci_lock_host: Failed to generate host path for host

> If sendmail could not lock the status file, it prints:

> >     mci_lock_host: couldn't get lock on filename

> When sendmail is about to update a status file, just before unlocking that file, it announces that fact:

> >     mci_unlock_host: store prior to unlock

> The process of updating or reading a status file begins by sendmail traversing the directory hierarchy under which that file is stored. If sendmail is unable to stat(2) any component of that path, it prints the following error:

> >     mci_traverse: Failed to stat component: reason for failure

> If sendmail cannot descend into the next directory, it prints:

> >     mci_traverse: opendir component: reason for failure

> When purging its host information with the purgestat(1) command (see Section 36.1.4), if sendmail cannot remove the status file, it prints:

> >     mci_purge_persistent: failed to unlink filename: reason for failure

> And if it cannot remove any of the directory components, it prints:

> >     mci_purge_persistent: rmdir directory: reason for failure

### 37.5.180 -d56.12

Perform a sanity check

> As a "sanity check," the `-d56.12` debugging switch causes sendmail to print the following if the lock was successfully acquired on the status file:

> >     mci_lock_host: Sanity check - lock is good

### 37.5.181 -d56.80

Trace creating the path to the status file

> If the status file does not exist, sendmail recursively makes the directories leading to it. The `-d56.80` debugging switch is used to trace this process:

> >     mci_generate_persistent_path(host): FAILURE errno
> >     mci_generate_persistent_path(host): SUCCESS path

> If this process of making directories fails, `errno` is printed, as listed in <errno.h>. If it succeeds, the `path` created is displayed.

### 37.5.182 -d56.93

Dump MCI record for the host

> The `-d56.93` debugging switch causes sendmail to dump the connection cache information associated with a host's status file:

> >     mci_read_persistent: fp=hex, mci= output of mci_dump() here (see Section 37.5.44)

> Here, `hex` is the file pointer of the open status file printed in hexadecimal. That is followed by a dump of the MCI record for the host.

### 37.5.183 -d57.2

Monitor vsnprintf() overflows

> If HASSNPRINTF is not defined, sendmail emulates the snprintf(3) function. If the internal buffer of that emulation overflows, the `-d57.2` debugging switch causes this warning to be printed:

> >     vsnprintf overflow: first 200 characters of buffer

> Note that you may have to also use the `-v` command-line switch to make this output visible.

### 37.5.184 -d59

XLA from contrib

(obsolete)

> See the XLA package in the contrib/xla directory as distributed with the V8 sendmail source. Note that XLA is no longer distributed with sendmail as of V8.8.

### 37.5.185 -d60.1

Trace map lookups inside rewrite()

(useful)

> Rules defined by the `R` configuration command are rewritten by sendmail's internal rewrite() subroutine. The `$[` and `$(` lookup operators (see Section 33.4.3, "$[ and $]: A Special Case" and Section 33.4, "Use Maps with $( and $) in Rules") cause sendmail to look up keys in databases (maps).

> If sendmail is running in deferred mode (see Section 34.8.16), it skips map lookups because they may cause DNS accesses. The `-d60.1` (a.k.a. `-d60`) debugging switch causes sendmail to print that it is skipping the lookup:

> >     map_lookup(name, key) => DEFERRED

> Here, `name` is the map type, such as `dequote` or `host`. The `key` is the information being looked up.

> If running in something other than deferred mode, sendmail performs the lookup. If the lookup fails (if `key` is not found), sendmail prints:

> >     map_lookup(name, key) => NOT FOUND (stat)

> Here, `stat` is the number of the error that caused the failure. If it is 0, then the lookup failed merely because the `key` was not found. Otherwise, it corresponds to the error numbers in <sysexits.h>. Then if `stat` is the special value 75 (for EX_TEMPFAIL), sendmail also prints:

> >     map_lookup(name, key) tempfail: errno=err

> Here, `err` is the error number that corresponds to the errors listed in <errno.h>.

> If the `key` is successfully found, sendmail prints:

> >     map_lookup(name, key) => replacement value here (stat)

> Note that the replacement value will be whatever value was defined by the `-a` database switch when the `K` command defined the map (see Section 33.3.4.2, "-a append tag on successful match (V8.1 and above)").

### 37.5.186 -d61.10

Trace gethostbyname()

> The gethostbyname(3) library routine is called by sendmail every time sendmail needs to find the canonical name of a host. The `-d61.10` [20] debugging switch shows the result of that lookup:

> > [20] There is no `-d61.1` information.

> >     _switch_gethostbyname_r(host)... canonical name here
> >     __switch_gethostbyname(host)... canonical name here
> >     gethostbyname(host)... canonical name here

> In all three lines of output, the `host` was looked up to find its canonical name. If one was found, its canonical name is printed; otherwise, `failure` is printed. The first two lines show variations on gethostbyname(3) that was required by some early SysVR4-based machines. These represent sendmail's attempt to canonify the `host` no matter what.

### 37.5.187 -d62.1

Log file descriptors before and after all deliveries

> The `-d62.1` (a.k.a. `-d62`) debugging switch causes sendmail to log the state of all of its file descriptors. It does this once just before it starts to process the list of its recipients and again just after it has completed delivery of all its recipients. Note that this debugging switch is unusual in that it causes its output to be logged with syslog(3), rather than written to stdout.

### 37.5.188 -d62.8

Log file descriptors before each delivery

> The `-d62.8` debugging switch causes sendmail to log the state of all its file descriptors just before undertaking delivery of each message.

### 37.5.189 -d62.10

Log file descriptors after each delivery

> The `-d62.10` debugging switch causes sendmail to log the state of all its file descriptors just after completing delivery of each message.

### 37.5.190 -d80.1

Content-Length: header (Sun enhancement)

> The `-d80.1` (a.k.a. `-d80`) debugging switch is used to watch how Sun's version of sendmail handles the `Content-Length:` header. As soon as the size of the body of a message is known, Sun's sendmail stores it in the envelope information. When the time comes to emit the `Content-Length:` header, that information is fetched. If the size is unknown, the `-d80.1` debugging switch causes sendmail to print:

> >     content_length(): Error:  Message bodysize undefined !

> If the size is known, it is reduced by the number and size of the end-of-line characters (as defined by the delivery agent's `E =` equate). If the delivery agent's `F=E` flag is set (see Section 30.8.19, F=E), the size is further reduced by the number of five character "`From` " strings that begin lines in the message body. The `-d80` debugging switch then causes the final result to be printed:

> >     Content length =  final length here

### 37.5.191 -d81.1

> option for remote mode (Sun enhancement)

> In V8.1 sendmail the letter `R` was co-opted by the Berkeley distribution as an option name. This forced Sun to change the name of its former `R` option into the new `>` option. The `-d81.1` (a.k.a. `-d80`) debugging switch causes Sun's sendmail to display the status of this remote mode:

> >     verify_mail_server(): remote mode is  either on or off
> >     mail server =  host name here

> If the `>` option is declared, `on` is printed, and the name of the remote mail host is displayed, if known. See Section 38.18, "The > Option" for a further description of this option.

### 37.5.192 -d91.100

Log caching and uncaching connections

> The `-d91.100` debugging switch [21] causes the same information to be logged with syslog(3) as is printed by the `-d42.5` debugging switch.

> > [21] There is no `-d91.1` information available.

### 37.5.193 -d99.100

Prevent backgrounding the daemon

(useful)

> The `-d99.100` debugging switch [22] prevents the sendmail daemon from forking and putting itself into the background. This leaves the running daemon connected to your terminal so that you can see other debugging output. For example,

> > [22] There is no `-d99.1` information available.

> >     # /usr/lib/sendmail -bd -d99.100 -d9.30

> This allows you to watch the daemon perform RFC1413 identification queries when SMTP connections are made. See also `-d52.100`, which prevents sendmail from disconnecting from its controlling terminal device, or the `-bD` command-line switch (Section 36.7.4, -bD), which does both.

37.4 Pitfalls |  | 38. Rule-Set Testing with -bt